1 /*
2 * Copyright (c) 2022-2023, 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_decode_base_specific.cpp
24 //! \brief The class implementation of DdiDecodeBase for all decoders
25 //!
26
27 #include "ddi_vp_functions.h"
28 #include "media_libva_util_next.h"
29 #include "media_interfaces_codechal.h"
30 #include "media_interfaces_mmd_next.h"
31 #include "mos_solo_generic.h"
32 #include "ddi_decode_base_specific.h"
33 #include "media_libva_common_next.h"
34 #include "media_interfaces_codechal_next.h"
35 #include "ddi_decode_trace_specific.h"
36 #include "media_libva_caps_next.h"
37
38 namespace decode
39 {
40
DdiDecodeBase()41 DdiDecodeBase::DdiDecodeBase()
42 : DdiCodecBase()
43 {
44 DDI_CODEC_FUNC_ENTER;
45
46 m_decodeCtx = nullptr;
47 MOS_ZeroMemory(&m_destSurface, sizeof(m_destSurface));
48 m_groupIndex = 0;
49 m_picWidthInMB = 0;
50 m_picHeightInMB = 0;
51 m_decProcessingType = 0;
52 m_width = 0;
53 m_height = 0;
54 m_streamOutEnabled = false;
55 m_sliceParamBufNum = 0;
56 m_sliceCtrlBufNum = 0;
57 m_codechalSettings = CodechalSetting::CreateCodechalSetting();
58 }
59
BasicInit(ConfigLinux * configItem)60 VAStatus DdiDecodeBase::BasicInit(
61 ConfigLinux *configItem)
62 {
63 DDI_CODEC_FUNC_ENTER;
64
65 if (configItem == nullptr)
66 {
67 return VA_STATUS_ERROR_ALLOCATION_FAILED;
68 }
69
70 m_ddiDecodeAttr = (ConfigLinux *)MOS_AllocAndZeroMemory(sizeof(ConfigLinux));
71 if (m_ddiDecodeAttr && configItem)
72 {
73 MOS_SecureMemcpy(m_ddiDecodeAttr, sizeof(ConfigLinux), configItem, sizeof(ConfigLinux));
74 }
75
76 m_decodeCtx = (DDI_DECODE_CONTEXT *)MOS_AllocAndZeroMemory(sizeof(DDI_DECODE_CONTEXT));
77
78 if ((m_ddiDecodeAttr == nullptr) ||
79 (m_decodeCtx == nullptr))
80 {
81 MOS_FreeMemory(m_ddiDecodeAttr);
82 m_ddiDecodeAttr = nullptr;
83 MOS_FreeMemory(m_decodeCtx);
84 m_decodeCtx = nullptr;
85 return VA_STATUS_ERROR_ALLOCATION_FAILED;
86 }
87
88 return VA_STATUS_SUCCESS;
89 }
90
GetBsBufOffset(int32_t sliceGroup)91 uint32_t DdiDecodeBase::GetBsBufOffset(int32_t sliceGroup)
92 {
93 DDI_CODEC_FUNC_ENTER;
94
95 return m_decodeCtx->BufMgr.pSliceData[sliceGroup].uiOffset;
96 }
97
ParseProcessingBuffer(DDI_MEDIA_CONTEXT * mediaCtx,void * bufAddr)98 VAStatus DdiDecodeBase::ParseProcessingBuffer(
99 DDI_MEDIA_CONTEXT *mediaCtx,
100 void *bufAddr)
101 {
102 DDI_CODEC_FUNC_ENTER;
103
104 #ifdef _DECODE_PROCESSING_SUPPORTED
105 VAProcPipelineParameterBuffer *procBuf =
106 (VAProcPipelineParameterBuffer *)bufAddr;
107
108 DDI_CODEC_CHK_NULL(procBuf, "nullptr Processing buffer", VA_STATUS_ERROR_INVALID_PARAMETER)
109
110 if (m_decProcessingType == VA_DEC_PROCESSING)
111 {
112 if (m_procBuf == nullptr)
113 {
114 m_procBuf = (VAProcPipelineParameterBuffer*)MOS_AllocAndZeroMemory(sizeof(VAProcPipelineParameterBuffer));
115 DDI_CODEC_CHK_NULL(m_procBuf, "nullptr m_procBuf", VA_STATUS_ERROR_ALLOCATION_FAILED);
116 MOS_SecureMemcpy(m_procBuf, sizeof(VAProcPipelineParameterBuffer), procBuf, sizeof(VAProcPipelineParameterBuffer));
117 }
118 auto decProcessingParams =
119 (DecodeProcessingParams *)m_decodeCtx->DecodeParams.m_procParams;
120
121 auto decProcessingSurface = decProcessingParams->m_outputSurface;
122
123 memset(decProcessingSurface, 0, sizeof(MOS_SURFACE));
124
125 PDDI_MEDIA_SURFACE surface =
126 MediaLibvaCommonNext::GetSurfaceFromVASurfaceID(mediaCtx, procBuf->additional_outputs[0]);
127
128 DDI_CODEC_CHK_NULL(surface, "Null surface in Processing buffer", VA_STATUS_ERROR_INVALID_PARAMETER)
129
130 MediaLibvaCommonNext::MediaSurfaceToMosResource(surface, &(decProcessingSurface->OsResource));
131
132 decProcessingSurface->dwWidth = decProcessingSurface->OsResource.iWidth;
133 decProcessingSurface->dwHeight = decProcessingSurface->OsResource.iHeight;
134 decProcessingSurface->dwPitch = decProcessingSurface->OsResource.iPitch;
135 decProcessingSurface->TileType = decProcessingSurface->OsResource.TileType;
136 decProcessingSurface->Format = decProcessingSurface->OsResource.Format;
137
138 if (procBuf->surface_region != nullptr)
139 {
140 m_requireInputRegion = false;
141 decProcessingParams->m_inputSurfaceRegion.m_x = procBuf->surface_region->x;
142 decProcessingParams->m_inputSurfaceRegion.m_y = procBuf->surface_region->y;
143 decProcessingParams->m_inputSurfaceRegion.m_width = procBuf->surface_region->width;
144 decProcessingParams->m_inputSurfaceRegion.m_height = procBuf->surface_region->height;
145 }
146 else
147 {
148 m_requireInputRegion = true;
149 }
150
151 decProcessingParams->m_outputSurface = decProcessingSurface;
152 if (procBuf->output_region != nullptr)
153 {
154 decProcessingParams->m_outputSurfaceRegion.m_x = procBuf->output_region->x;
155 decProcessingParams->m_outputSurfaceRegion.m_y = procBuf->output_region->y;
156 decProcessingParams->m_outputSurfaceRegion.m_width = procBuf->output_region->width;
157 decProcessingParams->m_outputSurfaceRegion.m_height = procBuf->output_region->height;
158 }
159 else
160 {
161 decProcessingParams->m_outputSurfaceRegion.m_x = 0;
162 decProcessingParams->m_outputSurfaceRegion.m_y = 0;
163 decProcessingParams->m_outputSurfaceRegion.m_width = decProcessingSurface->dwWidth;
164 decProcessingParams->m_outputSurfaceRegion.m_height = decProcessingSurface->dwHeight;
165 }
166
167 // Interpolation flags
168 // Set the vdbox scaling mode
169 uint32_t uInterpolationflags = 0;
170 #if VA_CHECK_VERSION(1, 9, 0)
171 uInterpolationflags = procBuf->filter_flags & VA_FILTER_INTERPOLATION_MASK;
172 #endif
173
174 switch (uInterpolationflags)
175 {
176 #if VA_CHECK_VERSION(1, 9, 0)
177 case VA_FILTER_INTERPOLATION_NEAREST_NEIGHBOR:
178 decProcessingParams->m_scalingMode = CODECHAL_SCALING_NEAREST;
179 break;
180 case VA_FILTER_INTERPOLATION_BILINEAR:
181 decProcessingParams->m_scalingMode = CODECHAL_SCALING_BILINEAR;
182 break;
183 case VA_FILTER_INTERPOLATION_ADVANCED:
184 case VA_FILTER_INTERPOLATION_DEFAULT:
185 #endif
186 default:
187 decProcessingParams->m_scalingMode = CODECHAL_SCALING_AVS;
188 break;
189 }
190
191 // Chroma siting
192 // Set the vertical chroma siting info
193 uint32_t chromaSitingFlags = 0;
194 chromaSitingFlags = procBuf->input_color_properties.chroma_sample_location & 0x3;
195 decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_NONE;
196 decProcessingParams->m_rotationState = 0;
197 decProcessingParams->m_blendState = 0;
198 decProcessingParams->m_mirrorState = 0;
199
200 switch (chromaSitingFlags)
201 {
202 case VA_CHROMA_SITING_VERTICAL_TOP:
203 decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_VERT_TOP;
204 break;
205 case VA_CHROMA_SITING_VERTICAL_CENTER:
206 decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_VERT_CENTER;
207 break;
208 case VA_CHROMA_SITING_VERTICAL_BOTTOM:
209 decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_VERT_BOTTOM;
210 break;
211 default:
212 decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_NONE;
213 break;
214 }
215
216 if (decProcessingParams->m_chromaSitingType != CODECHAL_CHROMA_SITING_NONE)
217 {
218 // Set the horizontal chroma siting info
219 chromaSitingFlags = procBuf->input_color_properties.chroma_sample_location & 0xc;
220
221 switch (chromaSitingFlags)
222 {
223 case VA_CHROMA_SITING_HORIZONTAL_LEFT:
224 decProcessingParams->m_chromaSitingType |= CODECHAL_CHROMA_SITING_HORZ_LEFT;
225 break;
226 case VA_CHROMA_SITING_HORIZONTAL_CENTER:
227 decProcessingParams->m_chromaSitingType |= CODECHAL_CHROMA_SITING_HORZ_CENTER;
228 break;
229 default:
230 decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_NONE;
231 break;
232 }
233 }
234 }
235
236 return VA_STATUS_SUCCESS;
237 #else
238 return VA_STATUS_ERROR_INVALID_PARAMETER;
239 #endif
240 }
241
BeginPicture(VADriverContextP ctx,VAContextID context,VASurfaceID renderTarget)242 VAStatus DdiDecodeBase::BeginPicture(
243 VADriverContextP ctx,
244 VAContextID context,
245 VASurfaceID renderTarget)
246 {
247 DDI_CODEC_FUNC_ENTER;
248
249 PDDI_MEDIA_CONTEXT mediaCtx;
250
251 /* As it is already checked in the upper caller, skip the check */
252 mediaCtx = GetMediaContext(ctx);
253
254 #ifdef _DECODE_PROCESSING_SUPPORTED
255 // renderTarget is decode output surface; set renderTarget as vp sfc input surface m_procBuf->surface = rederTarget
256 if (m_procBuf)
257 {
258 m_procBuf->surface = renderTarget;
259 }
260 #endif
261
262 DDI_MEDIA_SURFACE *curRT = nullptr;
263 curRT = (DDI_MEDIA_SURFACE *)MediaLibvaCommonNext::GetSurfaceFromVASurfaceID(mediaCtx, renderTarget);
264 DDI_CODEC_CHK_NULL(curRT, "nullptr pCurRT", VA_STATUS_ERROR_INVALID_SURFACE);
265 curRT->pDecCtx = m_decodeCtx;
266
267 DDI_CODEC_RENDER_TARGET_TABLE *RTtbl;
268 RTtbl = &(m_decodeCtx->RTtbl);
269 RTtbl->pCurrentRT = curRT;
270
271 m_streamOutEnabled = false;
272 m_decodeCtx->DecodeParams.m_numSlices = 0;
273 m_decodeCtx->DecodeParams.m_dataSize = 0;
274 m_decodeCtx->DecodeParams.m_dataOffset = 0;
275 m_decodeCtx->DecodeParams.m_deblockDataSize = 0;
276 m_decodeCtx->DecodeParams.m_executeCallIndex = 0;
277 m_decodeCtx->DecodeParams.m_cencBuf = nullptr;
278 m_groupIndex = 0;
279
280 // register render targets
281 DDI_CHK_RET(RegisterRTSurfaces(&m_decodeCtx->RTtbl, curRT),"RegisterRTSurfaces failed!");
282
283 if (nullptr == m_decodeCtx->pCodecHal)
284 {
285 return VA_STATUS_ERROR_ALLOCATION_FAILED;
286 }
287
288 MOS_STATUS eStatus = m_decodeCtx->pCodecHal->BeginFrame();
289 if (eStatus != MOS_STATUS_SUCCESS)
290 {
291 return VA_STATUS_ERROR_DECODING_ERROR;
292 }
293
294 return VA_STATUS_SUCCESS;
295 }
296
DecodeCombineBitstream(DDI_MEDIA_CONTEXT * mediaCtx)297 VAStatus DdiDecodeBase::DecodeCombineBitstream(DDI_MEDIA_CONTEXT *mediaCtx)
298 {
299 DDI_CODEC_FUNC_ENTER;
300
301 DDI_CODEC_COM_BUFFER_MGR *bufMgr = nullptr;
302 /* As it is checked in previous caller, it is skipped. */
303 bufMgr = &(m_decodeCtx->BufMgr);
304
305 if (bufMgr && (bufMgr->bIsSliceOverSize == false))
306 {
307 return VA_STATUS_SUCCESS;
308 }
309
310 PDDI_MEDIA_BUFFER newBitstreamBuffer;
311 // allocate a new bit stream buffer
312 newBitstreamBuffer = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
313 if (newBitstreamBuffer == nullptr)
314 {
315 DDI_CODEC_ASSERTMESSAGE("DDI:AllocAndZeroMem return failure.");
316 return VA_STATUS_ERROR_DECODING_ERROR;
317 }
318
319 newBitstreamBuffer->iSize = m_decodeCtx->DecodeParams.m_dataSize;
320 newBitstreamBuffer->uiType = VASliceDataBufferType;
321 newBitstreamBuffer->format = Media_Format_Buffer;
322 newBitstreamBuffer->uiOffset = 0;
323 newBitstreamBuffer->pMediaCtx = mediaCtx;
324
325 VAStatus vaStatus;
326 vaStatus = MediaLibvaUtilNext::CreateBuffer(newBitstreamBuffer,
327 mediaCtx->pDrmBufMgr);
328 if (vaStatus != VA_STATUS_SUCCESS)
329 {
330 MOS_FreeMemory(newBitstreamBuffer);
331 newBitstreamBuffer = nullptr;
332 return VA_STATUS_ERROR_ALLOCATION_FAILED;
333 }
334
335 uint8_t *newBitStreamBase = nullptr;
336 newBitStreamBase = (uint8_t *)MediaLibvaUtilNext::LockBuffer(newBitstreamBuffer, MOS_LOCKFLAG_WRITEONLY);
337
338 if (newBitStreamBase == nullptr)
339 {
340 MediaLibvaUtilNext::FreeBuffer(newBitstreamBuffer);
341 MOS_FreeMemory(newBitstreamBuffer);
342 newBitstreamBuffer = nullptr;
343 return VA_STATUS_ERROR_ALLOCATION_FAILED;
344 }
345
346 uint32_t slcInd = 0;
347 // copy data to new bit stream
348 for (slcInd = 0; slcInd < bufMgr->dwNumSliceData; slcInd++)
349 {
350 if (bufMgr->pSliceData[slcInd].bIsUseExtBuf == true)
351 {
352 if (bufMgr->pSliceData[slcInd].pSliceBuf)
353 {
354 MOS_SecureMemcpy(newBitStreamBase + bufMgr->pSliceData[slcInd].uiOffset,
355 bufMgr->pSliceData[slcInd].uiLength,
356 bufMgr->pSliceData[slcInd].pSliceBuf,
357 bufMgr->pSliceData[slcInd].uiLength);
358 MOS_FreeMemory(bufMgr->pSliceData[slcInd].pSliceBuf);
359 bufMgr->pSliceData[slcInd].pSliceBuf = nullptr;
360 bufMgr->pSliceData[slcInd].bIsUseExtBuf = false;
361 }
362 }
363 else
364 {
365 MOS_SecureMemcpy(newBitStreamBase + bufMgr->pSliceData[slcInd].uiOffset,
366 bufMgr->pSliceData[slcInd].uiLength,
367 bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] + bufMgr->pSliceData[slcInd].uiOffset,
368 bufMgr->pSliceData[slcInd].uiLength);
369 }
370 }
371
372 // free original buffers
373 if (bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex])
374 {
375 MediaLibvaUtilNext::UnlockBuffer(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]);
376 bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] = nullptr;
377 }
378
379 if (bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex])
380 {
381 MediaLibvaUtilNext::FreeBuffer(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]);
382 MOS_FreeMemory(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]);
383 bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex] = nullptr;
384 }
385
386 // set new bitstream buffer
387 bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex] = newBitstreamBuffer;
388 bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] = newBitStreamBase;
389 MediaLibvaCommonNext::MediaBufferToMosResource(m_decodeCtx->BufMgr.pBitStreamBuffObject[bufMgr->dwBitstreamIndex], &m_decodeCtx->BufMgr.resBitstreamBuffer);
390
391 return VA_STATUS_SUCCESS;
392 }
393
CheckDecodeResolution(ConfigLinux * configItem,uint32_t width,uint32_t height)394 VAStatus DdiDecodeBase::CheckDecodeResolution(
395 ConfigLinux *configItem,
396 uint32_t width,
397 uint32_t height)
398 {
399 DDI_CODEC_FUNC_ENTER;
400 uint32_t maxWidth = 0;
401 uint32_t maxHeight = 0;
402
403 DDI_CODEC_CHK_NULL(configItem, "nullptr configItem", VA_STATUS_ERROR_INVALID_CONFIG);
404 VAConfigAttrib *supportedAttribList = configItem->attribList;
405 DDI_CODEC_CHK_NULL(supportedAttribList, "nullptr supportedAttribList", VA_STATUS_ERROR_INVALID_CONFIG);
406
407 // parse supported width and height from capstable attributes
408 for (uint32_t i = 0; i < configItem->numAttribs; i++)
409 {
410 if (supportedAttribList[i].type == VAConfigAttribMaxPictureWidth)
411 {
412 maxWidth = supportedAttribList[i].value;
413 }
414 else if (supportedAttribList[i].type == VAConfigAttribMaxPictureHeight)
415 {
416 maxHeight = supportedAttribList[i].value;
417 }
418 else
419 {
420 continue;
421 }
422 }
423
424 if (width > maxWidth || height > maxHeight)
425 {
426 return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
427 }
428 else
429 {
430 return VA_STATUS_SUCCESS;
431 }
432
433 }
434
DestroyContext(VADriverContextP ctx)435 void DdiDecodeBase::DestroyContext(VADriverContextP ctx)
436 {
437 DDI_CODEC_FUNC_ENTER;
438
439 Codechal *codecHal = nullptr;
440 /* as they are already checked in caller, this is skipped */
441 codecHal = m_decodeCtx->pCodecHal;
442
443 if (codecHal != nullptr)
444 {
445 if (codecHal->GetOsInterface() && codecHal->GetOsInterface()->pOsContext)
446 {
447 MOS_FreeMemory(codecHal->GetOsInterface()->pOsContext->pPerfData);
448 codecHal->GetOsInterface()->pOsContext->pPerfData = nullptr;
449 }
450
451 // destroy codechal
452 codecHal->Destroy();
453 MOS_Delete(codecHal);
454
455 m_decodeCtx->pCodecHal = nullptr;
456 }
457
458 int32_t i = 0;
459 for (i = 0; i < DDI_MEDIA_MAX_SURFACE_NUMBER_CONTEXT; i++)
460 {
461 if ((m_decodeCtx->RTtbl.pRT[i] != nullptr) &&
462 (m_decodeCtx->RTtbl.pRT[i]->pDecCtx == m_decodeCtx))
463 {
464 m_decodeCtx->RTtbl.pRT[i]->pDecCtx = nullptr;
465 }
466 }
467
468 if (m_decodeCtx->pCpDdiInterfaceNext)
469 {
470 MOS_Delete(m_decodeCtx->pCpDdiInterfaceNext);
471 }
472
473 MOS_FreeMemory(m_decodeCtx->DecodeParams.m_iqMatrixBuffer);
474 m_decodeCtx->DecodeParams.m_iqMatrixBuffer = nullptr;
475
476 MOS_FreeMemory(m_decodeCtx->DecodeParams.m_huffmanTable);
477 m_decodeCtx->DecodeParams.m_huffmanTable = nullptr;
478
479 MOS_FreeMemory(m_decodeCtx->DecodeParams.m_picParams);
480 m_decodeCtx->DecodeParams.m_picParams = nullptr;
481
482 MOS_FreeMemory(m_decodeCtx->DecodeParams.m_sliceParams);
483 m_decodeCtx->DecodeParams.m_sliceParams = nullptr;
484
485 MOS_FreeMemory(m_decodeCtx->DecodeParams.m_extPicParams);
486 m_decodeCtx->DecodeParams.m_sliceParams = nullptr;
487
488 MOS_FreeMemory(m_decodeCtx->DecodeParams.m_advPicParams);
489 m_decodeCtx->DecodeParams.m_sliceParams = nullptr;
490
491 MOS_FreeMemory(m_decodeCtx->DecodeParams.m_extSliceParams);
492 m_decodeCtx->DecodeParams.m_sliceParams = nullptr;
493
494 MOS_FreeMemory(m_decodeCtx->DecodeParams.m_subsetParams);
495 m_decodeCtx->DecodeParams.m_sliceParams = nullptr;
496
497 #ifdef _DECODE_PROCESSING_SUPPORTED
498 if (m_decodeCtx->DecodeParams.m_procParams != nullptr)
499 {
500 auto procParams =
501 (DecodeProcessingParams *)m_decodeCtx->DecodeParams.m_procParams;
502 MOS_FreeMemory(procParams->m_outputSurface);
503 procParams->m_outputSurface = nullptr;
504
505 MOS_FreeMemory(m_decodeCtx->DecodeParams.m_procParams);
506 m_decodeCtx->DecodeParams.m_procParams = nullptr;
507 }
508 #endif
509
510 return;
511 }
512
GetBitstreamBufIndexFromBuffer(DDI_CODEC_COM_BUFFER_MGR * bufMgr,DDI_MEDIA_BUFFER * buf)513 int32_t DdiDecodeBase::GetBitstreamBufIndexFromBuffer(DDI_CODEC_COM_BUFFER_MGR *bufMgr, DDI_MEDIA_BUFFER *buf)
514 {
515 DDI_CODEC_FUNC_ENTER;
516
517 int32_t i = 0;
518 for(i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
519 {
520 if (bufMgr->pBitStreamBuffObject[i]->bo == buf->bo)
521 {
522 return i;
523 }
524 }
525
526 return DDI_CODEC_INVALID_BUFFER_INDEX;
527 }
528
AllocBsBuffer(DDI_CODEC_COM_BUFFER_MGR * bufMgr,DDI_MEDIA_BUFFER * buf)529 VAStatus DdiDecodeBase::AllocBsBuffer(
530 DDI_CODEC_COM_BUFFER_MGR *bufMgr,
531 DDI_MEDIA_BUFFER *buf)
532 {
533 DDI_CODEC_FUNC_ENTER;
534
535 uint32_t index = 0, i = 0;
536 VAStatus vaStatus = VA_STATUS_SUCCESS;
537 uint8_t *sliceBuf = nullptr;
538 DDI_MEDIA_BUFFER *bsBufObj = nullptr;
539 uint8_t *bsBufBaseAddr = nullptr;
540 bool createBsBuffer = false;
541
542 if (nullptr == bufMgr || nullptr == buf || nullptr == (m_decodeCtx->pMediaCtx))
543 {
544 DDI_CODEC_ASSERTMESSAGE("invalidate input parameters.");
545 return VA_STATUS_ERROR_ALLOCATION_FAILED;
546 }
547
548 index = bufMgr->dwNumSliceData;
549
550 /* the pSliceData needs to be reallocated in order to contain more SliceDataBuf */
551 if (index >= bufMgr->m_maxNumSliceData)
552 {
553 /* In theroy it can resize the m_maxNumSliceData one by one. But in order to
554 * avoid calling realloc frequently, it will try to allocate 10 to hold more
555 * SliceDataBuf. This is only for the optimized purpose.
556 */
557 int32_t reallocSize = bufMgr->m_maxNumSliceData + 10;
558
559 bufMgr->pSliceData = (DDI_CODEC_BITSTREAM_BUFFER_INFO *)realloc(bufMgr->pSliceData, sizeof(bufMgr->pSliceData[0]) * reallocSize);
560
561 if (bufMgr->pSliceData == nullptr)
562 {
563 DDI_CODEC_ASSERTMESSAGE("fail to reallocate pSliceData\n.");
564 return VA_STATUS_ERROR_ALLOCATION_FAILED;
565 }
566 memset(bufMgr->pSliceData + bufMgr->m_maxNumSliceData, 0,
567 sizeof(bufMgr->pSliceData[0]) * 10);
568
569 bufMgr->m_maxNumSliceData += 10;
570 }
571
572 if (index >= 1)
573 {
574 buf->uiOffset = bufMgr->pSliceData[index-1].uiOffset + bufMgr->pSliceData[index-1].uiLength;
575 if ((buf->uiOffset + buf->iSize) > bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]->iSize)
576 {
577 sliceBuf = (uint8_t*)MOS_AllocAndZeroMemory(buf->iSize);
578 if (sliceBuf == nullptr)
579 {
580 DDI_CODEC_ASSERTMESSAGE("DDI:AllocAndZeroMem return failure.")
581 return VA_STATUS_ERROR_ALLOCATION_FAILED;
582 }
583 bufMgr->bIsSliceOverSize = true;
584 }
585 else
586 {
587 bufMgr->bIsSliceOverSize = false;
588 }
589 }
590 else
591 {
592 bufMgr->bIsSliceOverSize = false;
593 for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
594 {
595 if (bufMgr->pBitStreamBuffObject[i]->bo != nullptr)
596 {
597 if (!mos_bo_busy(bufMgr->pBitStreamBuffObject[i]->bo))
598 {
599 // find a bitstream buffer whoes graphic memory is allocated but not used by HW now.
600 break;
601 }
602 }
603 else
604 {
605 // find a new bitstream buffer whoes graphic memory is not allocated yet
606 break;
607 }
608 }
609
610 if (i == DDI_CODEC_MAX_BITSTREAM_BUFFER)
611 {
612 // find the oldest bistream buffer which is the most possible one to become free in the shortest time.
613 bufMgr->dwBitstreamIndex = (bufMgr->ui64BitstreamOrder >> (DDI_CODEC_BITSTREAM_BUFFER_INDEX_BITS * DDI_CODEC_MAX_BITSTREAM_BUFFER_MINUS1)) & DDI_CODEC_MAX_BITSTREAM_BUFFER_INDEX;
614 // wait until decode complete
615 mos_bo_wait_rendering(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]->bo);
616 }
617 else
618 {
619 bufMgr->dwBitstreamIndex = i;
620 }
621 bufMgr->ui64BitstreamOrder = (bufMgr->ui64BitstreamOrder << 4) + bufMgr->dwBitstreamIndex;
622
623 bsBufObj = bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex];
624 bsBufObj->pMediaCtx = m_decodeCtx->pMediaCtx;
625 bsBufBaseAddr = bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex];
626
627 if (bsBufBaseAddr == nullptr)
628 {
629 createBsBuffer = true;
630 if (buf->iSize > bsBufObj->iSize)
631 {
632 bsBufObj->iSize = buf->iSize;
633 }
634 }
635 else if (buf->iSize > bsBufObj->iSize)
636 {
637 // free bo
638 MediaLibvaUtilNext::UnlockBuffer(bsBufObj);
639 MediaLibvaUtilNext::FreeBuffer(bsBufObj);
640 bsBufBaseAddr = nullptr;
641
642 createBsBuffer = true;
643 bsBufObj->iSize = buf->iSize;
644 }
645
646 if (createBsBuffer)
647 {
648 if (VA_STATUS_SUCCESS != MediaLibvaUtilNext::CreateBuffer(bsBufObj, m_decodeCtx->pMediaCtx->pDrmBufMgr))
649 {
650 return VA_STATUS_ERROR_ALLOCATION_FAILED;
651 }
652
653 bsBufBaseAddr = (uint8_t*)MediaLibvaUtilNext::LockBuffer(bsBufObj, MOS_LOCKFLAG_WRITEONLY);
654 if (bsBufBaseAddr == nullptr)
655 {
656 MediaLibvaUtilNext::FreeBuffer(bsBufObj);
657 return VA_STATUS_ERROR_ALLOCATION_FAILED;
658 }
659 bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] = bsBufBaseAddr;
660 }
661 }
662
663 if (bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] == nullptr)
664 {
665 return VA_STATUS_ERROR_ALLOCATION_FAILED;
666 }
667
668 bufMgr->pSliceData[index].uiLength = buf->iSize;
669 bufMgr->pSliceData[index].uiOffset = buf->uiOffset;
670
671 if (bufMgr->bIsSliceOverSize == true)
672 {
673 buf->pData = sliceBuf;
674 buf->uiOffset = 0;
675 bufMgr->pSliceData[index].bIsUseExtBuf = true;
676 bufMgr->pSliceData[index].pSliceBuf = sliceBuf;
677 buf->bCFlushReq = false;
678 }
679 else
680 {
681 buf->pData = (uint8_t*)(bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex]);
682 bufMgr->pSliceData[index].bIsUseExtBuf = false;
683 bufMgr->pSliceData[index].pSliceBuf = nullptr;
684 buf->bCFlushReq = true;
685 }
686
687 bufMgr->dwNumSliceData ++;
688 buf->bo = bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]->bo;
689
690 return VA_STATUS_SUCCESS;
691 }
692
GetFormat()693 MOS_FORMAT DdiDecodeBase::GetFormat()
694 {
695 DDI_CODEC_FUNC_ENTER;
696
697 return Format_NV12;
698 }
699
InitDecodeParams(VADriverContextP ctx,VAContextID context)700 VAStatus DdiDecodeBase::InitDecodeParams(
701 VADriverContextP ctx,
702 VAContextID context)
703 {
704 DDI_CODEC_FUNC_ENTER;
705
706 /* skip the mediaCtx check as it is checked in caller */
707 PDDI_MEDIA_CONTEXT mediaCtx;
708 mediaCtx = GetMediaContext(ctx);
709 DDI_CHK_RET(DecodeCombineBitstream(mediaCtx),"DecodeCombineBitstream failed!");
710 DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_decodeCtx->BufMgr);
711 bufMgr->dwNumSliceData = 0;
712 bufMgr->dwNumSliceControl = 0;
713 memset(&m_destSurface, 0, sizeof(MOS_SURFACE));
714 m_destSurface.dwOffset = 0;
715
716 DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_decodeCtx->RTtbl);
717
718 if ((rtTbl == nullptr) || (rtTbl->pCurrentRT == nullptr))
719 {
720 return VA_STATUS_ERROR_INVALID_PARAMETER;
721 }
722 return VA_STATUS_SUCCESS;
723
724 }
725
SetDecodeParams()726 VAStatus DdiDecodeBase::SetDecodeParams()
727 {
728 DDI_CODEC_FUNC_ENTER;
729
730 DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_decodeCtx->BufMgr);
731 if ((&m_decodeCtx->DecodeParams)->m_numSlices == 0)
732 {
733 return VA_STATUS_ERROR_INVALID_PARAMETER;
734 }
735
736 MOS_FORMAT expectedFormat = GetFormat();
737 m_destSurface.Format = expectedFormat;
738 MediaLibvaCommonNext::MediaSurfaceToMosResource((&(m_decodeCtx->RTtbl))->pCurrentRT, &(m_destSurface.OsResource));
739
740 if (m_destSurface.OsResource.Format != expectedFormat)
741 {
742 DDI_CODEC_NORMALMESSAGE("Surface fomrat of decoded surface is inconsistent with Codec bitstream\n");
743 return VA_STATUS_ERROR_INVALID_PARAMETER;
744 }
745
746 m_decodeCtx->DecodeParams.m_destSurface = &m_destSurface;
747 m_decodeCtx->DecodeParams.m_deblockSurface = nullptr;
748
749 m_decodeCtx->DecodeParams.m_dataBuffer = &bufMgr->resBitstreamBuffer;
750 m_decodeCtx->DecodeParams.m_bitStreamBufData = bufMgr->pBitstreamBuffer;
751
752 m_decodeCtx->DecodeParams.m_bitplaneBuffer = nullptr;
753
754 if (m_streamOutEnabled)
755 {
756 m_decodeCtx->DecodeParams.m_streamOutEnabled = true;
757 m_decodeCtx->DecodeParams.m_externalStreamOutBuffer = &bufMgr->resExternalStreamOutBuffer;
758 }
759 else
760 {
761 m_decodeCtx->DecodeParams.m_streamOutEnabled = false;
762 m_decodeCtx->DecodeParams.m_externalStreamOutBuffer = nullptr;
763 }
764
765 if (m_decodeCtx->pCpDdiInterfaceNext)
766 {
767 DDI_CHK_RET(m_decodeCtx->pCpDdiInterfaceNext->SetDecodeParams(m_decodeCtx, m_codechalSettings), "SetDecodeParams failed!");
768 }
769
770 Mos_Solo_OverrideBufferSize(m_decodeCtx->DecodeParams.m_dataSize, m_decodeCtx->DecodeParams.m_dataBuffer);
771
772 return VA_STATUS_SUCCESS;
773 }
774
ExtraDownScaling(VADriverContextP ctx,VAContextID context)775 VAStatus DdiDecodeBase::ExtraDownScaling(
776 VADriverContextP ctx,
777 VAContextID context)
778 {
779 DDI_CODEC_FUNC_ENTER;
780
781 #ifdef _DECODE_PROCESSING_SUPPORTED
782 DDI_CODEC_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
783 VAStatus vaStatus = MOS_STATUS_SUCCESS;
784 PDDI_MEDIA_CONTEXT mediaCtx = GetMediaContext(ctx);
785 DDI_CODEC_CHK_NULL(mediaCtx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
786 DDI_CODEC_CHK_NULL(m_decodeCtx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
787
788 bool isDecodeDownScalingSupported = false;
789 DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(m_decodeCtx->pCodecHal);
790 DDI_CODEC_CHK_NULL(decoder, "nullptr decoder", VA_STATUS_ERROR_INVALID_PARAMETER);
791 isDecodeDownScalingSupported = decoder->IsDownSamplingSupported();
792
793 if (m_decodeCtx->DecodeParams.m_procParams != nullptr &&
794 m_procBuf &&
795 !isDecodeDownScalingSupported)
796 {
797 // check vp context
798 VAContextID vpCtxID = VA_INVALID_ID;
799 if (mediaCtx->pVpCtxHeap != nullptr && mediaCtx->pVpCtxHeap->pHeapBase != nullptr)
800 {
801 // Get VP Context from heap.
802 vpCtxID = (VAContextID)(0 + DDI_MEDIA_SOFTLET_VACONTEXTID_VP_OFFSET);
803 }
804 else
805 {
806 // Create VP Context.
807 vaStatus = mediaCtx->m_compList[CompVp]->CreateContext(ctx, 0, 0, 0, 0, 0, 0, &vpCtxID);
808 DDI_CHK_RET(vaStatus, "Create VP Context failed.");
809 }
810
811 uint32_t ctxType;
812 PDDI_VP_CONTEXT pVpCtx = (PDDI_VP_CONTEXT)MediaLibvaCommonNext::GetContextFromContextID(ctx, vpCtxID, &ctxType);
813 DDI_CODEC_CHK_NULL(pVpCtx, "nullptr pVpCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
814
815 // Set parameters
816 VAProcPipelineParameterBuffer* pInputPipelineParam = m_procBuf;
817 DDI_CODEC_CHK_NULL(pInputPipelineParam, "nullptr pInputPipelineParam", VA_STATUS_ERROR_ALLOCATION_FAILED);
818
819 vaStatus = mediaCtx->m_compList[CompVp]->BeginPicture(ctx, vpCtxID, pInputPipelineParam->additional_outputs[0]);
820 DDI_CHK_RET(vaStatus, "VP BeginPicture failed");
821
822 vaStatus = m_decodeCtx->pVpDdiInterface->DdiSetProcPipelineParams(ctx, pVpCtx, pInputPipelineParam);
823 DDI_CHK_RET(vaStatus, "VP SetProcPipelineParams failed.");
824
825 vaStatus = mediaCtx->m_compList[CompVp]->EndPicture(ctx, vpCtxID);
826 DDI_CHK_RET(vaStatus, "VP EndPicture failed.");
827 }
828 #endif
829 return MOS_STATUS_SUCCESS;
830 }
831
InitDummyReference(CodechalDecode & decoder)832 VAStatus DdiDecodeBase::InitDummyReference(CodechalDecode& decoder)
833 {
834 DDI_CODEC_FUNC_ENTER;
835
836 PMOS_SURFACE dummyReference = decoder.GetDummyReference();
837
838 // If dummy reference is from decode output surface, need to update frame by frame
839 if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_DEST_SURFACE)
840 {
841 MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
842 decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
843 }
844
845 if (!Mos_ResourceIsNull(&dummyReference->OsResource))
846 {
847 Mos_Specific_GetResourceInfo(decoder.GetOsInterface(), &dummyReference->OsResource, dummyReference);
848
849 // Check if need to re-get dummy reference from DPB or re-allocated
850 if (dummyReference->dwWidth < m_decodeCtx->DecodeParams.m_destSurface->dwWidth ||
851 dummyReference->dwHeight < m_decodeCtx->DecodeParams.m_destSurface->dwHeight)
852 {
853 // Check if the dummy reference needs to be re-allocated
854 if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_ALLOCATED)
855 {
856 decoder.GetOsInterface()->pfnFreeResource(decoder.GetOsInterface(), &dummyReference->OsResource);
857 }
858
859 // Reset dummy reference
860 MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
861 decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
862
863 // Considering potential risk, disable the dummy reference from DPB path temporarily
864 //GetDummyReferenceFromDPB(m_decodeCtx);
865
866 //if (!Mos_ResourceIsNull(&dummyReference->OsResource))
867 //{
868 // decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
869 //}
870 }
871 }
872 else
873 {
874 // Init dummy reference
875 MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
876 decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
877
878 // Considering potential risk, disable the dummy reference from DPB path temporarily
879 //GetDummyReferenceFromDPB(m_decodeCtx);
880 //if (!Mos_ResourceIsNull(&dummyReference->OsResource))
881 //{
882 // decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
883 //}
884 }
885
886 return VA_STATUS_SUCCESS;
887 }
888
InitDummyReference(DecodePipelineAdapter & decoder)889 VAStatus DdiDecodeBase::InitDummyReference(DecodePipelineAdapter &decoder)
890 {
891 DDI_CODEC_FUNC_ENTER;
892
893 PMOS_SURFACE dummyReference = decoder.GetDummyReference();
894
895 // If dummy reference is from decode output surface, need to update frame by frame
896 if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_DEST_SURFACE)
897 {
898 MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
899 decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
900 }
901
902 if (!Mos_ResourceIsNull(&dummyReference->OsResource))
903 {
904 Mos_Specific_GetResourceInfo(decoder.GetOsInterface(), &dummyReference->OsResource, dummyReference);
905
906 // Check if need to re-get dummy reference from DPB or re-allocated
907 if (dummyReference->dwWidth < m_decodeCtx->DecodeParams.m_destSurface->dwWidth ||
908 dummyReference->dwHeight < m_decodeCtx->DecodeParams.m_destSurface->dwHeight)
909 {
910 // Check if the dummy reference needs to be re-allocated
911 if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_ALLOCATED)
912 {
913 decoder.GetOsInterface()->pfnFreeResource(decoder.GetOsInterface(), &dummyReference->OsResource);
914 }
915
916 // Reset dummy reference
917 MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
918 decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
919
920 // Considering potential risk, disable the dummy reference from DPB path temporarily
921 //GetDummyReferenceFromDPB(m_decodeCtx);
922
923 //if (!Mos_ResourceIsNull(&dummyReference->OsResource))
924 //{
925 // decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
926 //}
927 }
928 }
929 else
930 {
931 // Init dummy reference
932 MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
933 decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
934
935 // Considering potential risk, disable the dummy reference from DPB path temporarily
936 //GetDummyReferenceFromDPB(m_decodeCtx);
937 //if (!Mos_ResourceIsNull(&dummyReference->OsResource))
938 //{
939 // decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
940 //}
941 }
942
943 return VA_STATUS_SUCCESS;
944 }
945
EndPicture(VADriverContextP ctx,VAContextID context)946 VAStatus DdiDecodeBase::EndPicture(
947 VADriverContextP ctx,
948 VAContextID context)
949 {
950 DDI_CODEC_FUNC_ENTER;
951
952 if (m_decodeCtx->bDecodeModeReported == false)
953 {
954 ReportDecodeMode(m_decodeCtx->wMode);
955 m_decodeCtx->bDecodeModeReported = true;
956 }
957
958 DDI_CHK_RET(InitDecodeParams(ctx,context),"InitDecodeParams failed!");
959
960 DDI_CHK_RET(SetDecodeParams(), "SetDecodeParams failed!");
961 DDI_CHK_RET(ClearRefList(&(m_decodeCtx->RTtbl), m_withDpb), "ClearRefList failed!");
962 if (m_decodeCtx->pCodecHal == nullptr)
963 {
964 return VA_STATUS_ERROR_ALLOCATION_FAILED;
965 }
966
967 if (MEDIA_IS_WA(&m_decodeCtx->pMediaCtx->WaTable, WaDummyReference))
968 {
969 Mos_Specific_GetResourceInfo(
970 m_decodeCtx->pCodecHal->GetOsInterface(),
971 &m_decodeCtx->DecodeParams.m_destSurface->OsResource,
972 m_decodeCtx->DecodeParams.m_destSurface);
973
974 DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(m_decodeCtx->pCodecHal);
975 DDI_CODEC_CHK_NULL(decoder, "Null decoder", VA_STATUS_ERROR_INVALID_PARAMETER);
976 DDI_CHK_RET(InitDummyReference(*decoder), "InitDummyReference failed!");
977 }
978
979 MOS_STATUS status = m_decodeCtx->pCodecHal->Execute((void *)(&m_decodeCtx->DecodeParams));
980 if (status != MOS_STATUS_SUCCESS)
981 {
982 DDI_CODEC_ASSERTMESSAGE("DDI:DdiDecode_DecodeInCodecHal return failure.");
983 return VA_STATUS_ERROR_DECODING_ERROR;
984 }
985
986 m_decodeCtx->DecodeParams.m_executeCallIndex++;
987
988 (&(m_decodeCtx->RTtbl))->pCurrentRT = nullptr;
989
990 status = m_decodeCtx->pCodecHal->EndFrame();
991 if (status != MOS_STATUS_SUCCESS)
992 {
993 return VA_STATUS_ERROR_DECODING_ERROR;
994 }
995
996 #ifdef _DECODE_PROCESSING_SUPPORTED
997 if (ExtraDownScaling(ctx,context) != VA_STATUS_SUCCESS)
998 {
999 return VA_STATUS_ERROR_DECODING_ERROR;
1000 }
1001 #endif
1002
1003 return VA_STATUS_SUCCESS;
1004 }
1005
CreateBuffer(VABufferType type,uint32_t size,uint32_t numElements,void * data,VABufferID * bufId)1006 VAStatus DdiDecodeBase::CreateBuffer(
1007 VABufferType type,
1008 uint32_t size,
1009 uint32_t numElements,
1010 void *data,
1011 VABufferID *bufId)
1012 {
1013 DDI_CODEC_FUNC_ENTER;
1014
1015 DDI_MEDIA_BUFFER *buf = nullptr;
1016 PDDI_MEDIA_BUFFER_HEAP_ELEMENT bufferHeapElement;
1017 uint16_t segMapWidth = m_picWidthInMB;
1018 uint16_t segMapHeight = m_picHeightInMB;
1019 MOS_STATUS status = MOS_STATUS_SUCCESS;
1020 VAStatus va = VA_STATUS_SUCCESS;
1021
1022 // only for VASliceParameterBufferType of buffer, the number of elements can be greater than 1
1023 if (type != VASliceParameterBufferType && numElements > 1)
1024 {
1025 return VA_STATUS_ERROR_INVALID_PARAMETER;
1026 }
1027
1028 buf = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
1029 if (buf == nullptr)
1030 {
1031 return VA_STATUS_ERROR_ALLOCATION_FAILED;
1032 }
1033 buf->iSize = size * numElements;
1034 buf->uiNumElements = numElements;
1035 buf->uiType = type;
1036 buf->format = Media_Format_Buffer;
1037 buf->uiOffset = 0;
1038 buf->bCFlushReq = false;
1039 buf->pMediaCtx = m_decodeCtx->pMediaCtx;
1040
1041 switch ((int32_t)type)
1042 {
1043 case VABitPlaneBufferType:
1044 buf->pData = (uint8_t*)((m_decodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pBitPlaneBuffer));
1045 break;
1046 case VASliceDataBufferType:
1047 case VAProtectedSliceDataBufferType:
1048 va = AllocBsBuffer(&(m_decodeCtx->BufMgr), buf);
1049 if (va != VA_STATUS_SUCCESS)
1050 {
1051 MOS_FreeMemory(buf);
1052 return va;
1053 }
1054 break;
1055 case VASliceParameterBufferType:
1056 va = AllocSliceControlBuffer(buf);
1057 if (va != VA_STATUS_SUCCESS)
1058 {
1059 MOS_FreeMemory(buf);
1060 return va;
1061 }
1062 buf->format = Media_Format_CPU;
1063 break;
1064 case VAPictureParameterBufferType:
1065 buf->pData = GetPicParamBuf(&(m_decodeCtx->BufMgr));
1066 buf->format = Media_Format_CPU;
1067 break;
1068 case VASubsetsParameterBufferType:
1069 buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
1070 buf->format = Media_Format_CPU;
1071 break;
1072 case VAIQMatrixBufferType:
1073 buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
1074 buf->format = Media_Format_CPU;
1075 break;
1076 case VAProbabilityBufferType:
1077 buf->pData = (uint8_t*)(&(m_decodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.ProbabilityDataVP8));
1078 break;
1079 case VAProcFilterParameterBufferType:
1080 buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(sizeof(VAProcPipelineCaps));
1081 buf->format = Media_Format_CPU;
1082 break;
1083 case VAProcPipelineParameterBufferType:
1084 buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(sizeof(VAProcPipelineParameterBuffer));
1085 buf->format = Media_Format_CPU;
1086 break;
1087 case VADecodeStreamoutBufferType:
1088 {
1089 segMapHeight = ((segMapHeight + 1) >> 1); // uiSize must be equal and bigger than size for interlaced case
1090
1091 if (size < MOS_ALIGN_CEIL(segMapHeight * segMapWidth * CODEC_SIZE_MFX_STREAMOUT_DATA, 64))
1092 {
1093 va = VA_STATUS_ERROR_INVALID_PARAMETER;
1094 MOS_FreeMemory(buf);
1095 return va;
1096 }
1097 buf->iSize = size * numElements;
1098 buf->format = Media_Format_Buffer;
1099 va = MediaLibvaUtilNext::CreateBuffer(buf, m_decodeCtx->pMediaCtx->pDrmBufMgr);
1100 if (va != VA_STATUS_SUCCESS)
1101 {
1102 MOS_FreeMemory(buf);
1103 return va;
1104 }
1105 break;
1106 }
1107 case VAHuffmanTableBufferType:
1108 buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
1109 buf->format = Media_Format_CPU;
1110 break;
1111 #if VA_CHECK_VERSION(1, 10, 0)
1112 case VAContextParameterUpdateBufferType:
1113 {
1114 buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
1115 buf->format = Media_Format_CPU;
1116 break;
1117 }
1118 #endif
1119 default:
1120 va = m_decodeCtx->pCpDdiInterfaceNext->CreateBuffer(type, buf, size, numElements);
1121 if (va == VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE)
1122 {
1123 DDI_CODEC_ASSERTMESSAGE("DDI:Decode CreateBuffer unsuppoted buffer type.");
1124 buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
1125 buf->format = Media_Format_CPU;
1126 if (buf->pData != NULL)
1127 {
1128 va = VA_STATUS_SUCCESS;
1129 }
1130 }
1131 break;
1132 }
1133
1134 bufferHeapElement = MediaLibvaUtilNext::AllocPMediaBufferFromHeap(m_decodeCtx->pMediaCtx->pBufferHeap);
1135 if (nullptr == bufferHeapElement)
1136 {
1137 va = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
1138 MOS_FreeMemory(buf);
1139 return va;
1140 }
1141 bufferHeapElement->pBuffer = buf;
1142 bufferHeapElement->pCtx = (void*)m_decodeCtx;
1143 bufferHeapElement->uiCtxType = DDI_MEDIA_CONTEXT_TYPE_DECODER;
1144 *bufId = bufferHeapElement->uiVaBufferID;
1145
1146 // Keep record the VaBufferID of JPEG slice data buffer we allocated, in order to do buffer mapping when render this buffer. otherwise we
1147 // can not get correct buffer address when application create them disordered.
1148 if (type == VASliceDataBufferType && m_decodeCtx->wMode == CODECHAL_DECODE_MODE_JPEG)
1149 {
1150 // since the dwNumSliceData already +1 when allocate buffer, but here we need to track the VaBufferID before dwSliceData increased.
1151 m_decodeCtx->BufMgr.pSliceData[m_decodeCtx->BufMgr.dwNumSliceData - 1].vaBufferId = *bufId;
1152 }
1153 m_decodeCtx->pMediaCtx->uiNumBufs++;
1154
1155 if (data == nullptr)
1156 {
1157 return va;
1158 }
1159
1160 if (true == buf->bCFlushReq)
1161 {
1162 mos_bo_wait_rendering(buf->bo);
1163 }
1164 status = MOS_SecureMemcpy((void *)(buf->pData + buf->uiOffset), size * numElements, data, size * numElements);
1165 DDI_CHK_CONDITION((status != MOS_STATUS_SUCCESS), "DDI:Failed to copy buffer data!", VA_STATUS_ERROR_OPERATION_FAILED);
1166
1167 return va;
1168 }
1169
ContextInit(int32_t picWidth,int32_t picHeight)1170 void DdiDecodeBase::ContextInit(
1171 int32_t picWidth,
1172 int32_t picHeight)
1173 {
1174 DDI_CODEC_FUNC_ENTER;
1175
1176 m_width = picWidth;
1177 m_height = picHeight;
1178 m_picWidthInMB = (int16_t)(DDI_CODEC_NUM_MACROBLOCKS_WIDTH(picWidth));
1179 m_picHeightInMB = (int16_t)(DDI_CODEC_NUM_MACROBLOCKS_HEIGHT(picHeight));
1180 m_decodeCtx->wMode = CODECHAL_DECODE_MODE_AVCVLD;
1181 m_decodeCtx->bShortFormatInUse = false;
1182 #ifdef _DECODE_PROCESSING_SUPPORTED
1183 if (m_ddiDecodeAttr->componentData.data.processType == VA_DEC_PROCESSING)
1184 {
1185 DDI_CODEC_NORMALMESSAGE("Decoding context has scaling/format conversion capabilities");
1186 m_decProcessingType = VA_DEC_PROCESSING;
1187 }
1188 else
1189 #endif
1190 {
1191 DDI_CODEC_NORMALMESSAGE("Decoding context DOESN'T have scaling/format conversion capabilities");
1192 m_decProcessingType = VA_DEC_PROCESSING_NONE;
1193 }
1194 m_streamOutEnabled = false;
1195 m_decodeCtx->DecodeParams.m_picIdRemappingInUse = true;
1196 return;
1197 }
1198
CreateCodecHal(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr,_CODECHAL_STANDARD_INFO * standardInfo)1199 VAStatus DdiDecodeBase::CreateCodecHal(
1200 DDI_MEDIA_CONTEXT *mediaCtx,
1201 void *ptr,
1202 _CODECHAL_STANDARD_INFO *standardInfo)
1203 {
1204 DDI_CODEC_FUNC_ENTER;
1205
1206 if ((mediaCtx == nullptr) ||
1207 (ptr == nullptr) ||
1208 (m_codechalSettings == nullptr) ||
1209 (standardInfo == nullptr))
1210 {
1211 DDI_CODEC_ASSERTMESSAGE("NULL pointer is passed for CreateCodecHal.\n");
1212 return VA_STATUS_ERROR_INVALID_PARAMETER;
1213
1214 }
1215 MOS_CONTEXT *mosCtx = (MOS_CONTEXT *)ptr;
1216 VAStatus vaStatus = VA_STATUS_SUCCESS;
1217
1218 Codechal *codecHal = CodechalDeviceNext::CreateFactory(
1219 nullptr,
1220 mosCtx,
1221 standardInfo,
1222 m_codechalSettings);
1223
1224 if (nullptr == codecHal)
1225 {
1226 DDI_CODEC_ASSERTMESSAGE("Failure in CodecHal create.\n");
1227 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1228 return vaStatus;
1229 }
1230
1231 DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(codecHal);
1232 if (nullptr == decoder)
1233 {
1234 DDI_CODEC_ASSERTMESSAGE("Failure in CodecHal create.\n");
1235 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1236 return vaStatus;
1237 }
1238
1239 m_decodeCtx->pCodecHal = codecHal;
1240
1241 m_codechalSettings->sfcInUseHinted = true;
1242
1243 if (m_ddiDecodeAttr && m_ddiDecodeAttr->componentData.data.encryptType)
1244 {
1245 m_codechalSettings->secureMode = true;
1246 }
1247
1248 if (codecHal->Allocate(m_codechalSettings) != MOS_STATUS_SUCCESS)
1249 {
1250 DDI_CODEC_ASSERTMESSAGE("Failure in decode allocate.\n");
1251 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1252 return vaStatus;
1253 }
1254
1255 PMOS_INTERFACE osInterface = codecHal->GetOsInterface();
1256 if (osInterface == nullptr)
1257 {
1258 DDI_CODEC_ASSERTMESSAGE("Failure in decode allocate.\n");
1259 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1260 return vaStatus;
1261 }
1262
1263 m_decodeCtx->pCpDdiInterfaceNext->CreateCencDecode(codecHal->GetDebugInterface(), mosCtx, m_codechalSettings);
1264
1265 return vaStatus;
1266 }
1267
GetDummyReferenceFromDPB(DDI_DECODE_CONTEXT * decodeCtx)1268 void DdiDecodeBase::GetDummyReferenceFromDPB(
1269 DDI_DECODE_CONTEXT *decodeCtx)
1270 {
1271 DDI_CODEC_FUNC_ENTER;
1272
1273 MOS_SURFACE *destSurface = decodeCtx->DecodeParams.m_destSurface;
1274 MOS_SURFACE dummyReference;
1275 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1276 uint32_t i = 0;
1277
1278 if (destSurface == nullptr)
1279 {
1280 DDI_CODEC_ASSERTMESSAGE("Decode output surface is NULL.\n");
1281 return;
1282 }
1283
1284 for (i = 0; i < DDI_MEDIA_MAX_SURFACE_NUMBER_CONTEXT; i++)
1285 {
1286 if (decodeCtx->RTtbl.pRT[i] != nullptr &&
1287 decodeCtx->RTtbl.pRT[i] != decodeCtx->RTtbl.pCurrentRT)
1288 {
1289 MOS_ZeroMemory(&dummyReference, sizeof(MOS_SURFACE));
1290 MediaLibvaCommonNext::MediaSurfaceToMosResource(decodeCtx->RTtbl.pRT[i], &(dummyReference.OsResource));
1291
1292 if (!Mos_ResourceIsNull(&dummyReference.OsResource))
1293 {
1294 eStatus = MOS_STATUS_SUCCESS;
1295 dummyReference.Format = Format_Invalid;
1296 eStatus = Mos_Specific_GetResourceInfo(decodeCtx->pCodecHal->GetOsInterface(), &dummyReference.OsResource, &dummyReference);
1297 if (eStatus != MOS_STATUS_SUCCESS)
1298 {
1299 continue;
1300 }
1301
1302 if (dummyReference.Type == destSurface->Type &&
1303 dummyReference.Format == destSurface->Format &&
1304 dummyReference.bIsCompressed == destSurface->bIsCompressed &&
1305 dummyReference.CompressionMode == destSurface->CompressionMode &&
1306 dummyReference.TileType == destSurface->TileType &&
1307 dummyReference.dwPitch >= destSurface->dwPitch &&
1308 dummyReference.dwWidth >= destSurface->dwWidth &&
1309 dummyReference.dwHeight >= destSurface->dwHeight)
1310 {
1311 break;
1312 }
1313 }
1314 }
1315 }
1316
1317 if (i < DDI_MEDIA_MAX_SURFACE_NUMBER_CONTEXT)
1318 {
1319 DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(decodeCtx->pCodecHal);
1320 if (decoder == nullptr)
1321 {
1322 DDI_CODEC_ASSERTMESSAGE("Codechal decode context is NULL.\n");
1323 return;
1324 }
1325 decoder->GetDummyReference()->OsResource = dummyReference.OsResource;
1326 }
1327
1328 return;
1329 }
1330
ReportDecodeMode(uint16_t wMode)1331 void DdiDecodeBase::ReportDecodeMode(
1332 uint16_t wMode)
1333 {
1334 DDI_CODEC_FUNC_ENTER;
1335
1336 PMOS_INTERFACE osInterface = m_decodeCtx->pCodecHal ? m_decodeCtx->pCodecHal->GetOsInterface() : nullptr;
1337 MOS_CONTEXT_HANDLE ctxHandle = osInterface ? (MOS_CONTEXT_HANDLE)osInterface->pOsContext : nullptr;
1338
1339 MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData;
1340 MOS_ZeroMemory(&userFeatureWriteData, sizeof(userFeatureWriteData));
1341 userFeatureWriteData.Value.i32Data = wMode;
1342 switch (wMode)
1343 {
1344 case CODECHAL_DECODE_MODE_MPEG2IDCT:
1345 case CODECHAL_DECODE_MODE_MPEG2VLD:
1346 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_MPEG2_MODE_ID;
1347 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1348 break;
1349 case CODECHAL_DECODE_MODE_AVCVLD:
1350 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_AVC_MODE_ID;
1351 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1352 break;
1353 case CODECHAL_DECODE_MODE_JPEG:
1354 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_JPEG_MODE_ID;
1355 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1356 break;
1357 case CODECHAL_DECODE_MODE_VP8VLD:
1358 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_VP8_MODE_ID;
1359 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1360 break;
1361 case CODECHAL_DECODE_MODE_HEVCVLD:
1362 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_HEVC_MODE_ID;
1363 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1364 break;
1365 case CODECHAL_DECODE_MODE_VP9VLD:
1366 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_VP9_MODE_ID;
1367 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1368 break;
1369 case CODECHAL_DECODE_MODE_AV1VLD:
1370 userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_AV1_MODE_ID;
1371 MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1372 break;
1373 default:
1374 break;
1375 }
1376 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
1377 {
1378 DECODE_EVENTDATA_VA_FEATURE_REPORTMODE eventData;
1379 eventData.wMode = (uint32_t)wMode;
1380 eventData.ValueID = userFeatureWriteData.ValueID;
1381 MOS_TraceEvent(EVENT_DECODE_FEATURE_DECODEMODE_REPORTVA, EVENT_TYPE_INFO, &eventData, sizeof(eventData), NULL, 0);
1382 }
1383 #endif
1384 return;
1385 }
1386 } // namespace decode
1387