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