1 /*
2 * Copyright (c) 2009-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_libva_decoder.cpp
24 //! \brief libva(and its extension) decoder implementation.
25 //!
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sys/mman.h>
30 #include <sys/ioctl.h>
31 #include <unistd.h>
32
33 #include "media_libva_decoder.h"
34 #include "media_libva_util.h"
35 #include "media_libva_cp_interface.h"
36 #include "media_libva_caps.h"
37 #include "codechal_memdecomp.h"
38 #include "mos_solo_generic.h"
39 #include "media_ddi_factory.h"
40 #include "media_ddi_decode_base.h"
41 #include "media_factory.h"
42 #include "media_ddi_decode_const.h"
43 #include "decode_status_report.h"
44 #include "vphal_render_vebox_memdecomp.h"
45
46 #if !defined(ANDROID) && defined(X11_FOUND)
47 #include <X11/Xutil.h>
48 #endif
49
50 #include <linux/fb.h>
51
52 typedef MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR> DdiDecodeFactory;
53
DdiDecode_GetDisplayInfo(VADriverContextP ctx)54 static int32_t DdiDecode_GetDisplayInfo(VADriverContextP ctx)
55 {
56 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
57 {
58 MOS_TraceEvent(EVENT_DECODE_DDI_DISPLAYINFOVA, EVENT_TYPE_START, NULL, 0, NULL, 0);
59 }
60 #endif
61 PDDI_MEDIA_CONTEXT mediaDrvCtx = DdiMedia_GetMediaContext(ctx);
62 int32_t fd = -1;
63 struct fb_var_screeninfo vsinfo;
64 vsinfo.xres = 0;
65 vsinfo.yres = 0;
66
67 fd = open("/dev/graphics/fb0",O_RDONLY);
68 if(fd >= 0)
69 {
70 if(ioctl(fd, FBIOGET_VSCREENINFO, &vsinfo) < 0)
71 {
72 DDI_NORMALMESSAGE("ioctl: fail to get display information!\n");
73 }
74 close(fd);
75 }
76 else
77 {
78 DDI_NORMALMESSAGE("GetDisplayInfo: cannot open device!\n");
79 }
80
81 if(vsinfo.xres <= 0 || vsinfo.yres <= 0)
82 {
83 vsinfo.xres = 1280;
84 vsinfo.yres = 720;
85 }
86 mediaDrvCtx->uiDisplayWidth = vsinfo.xres;
87 mediaDrvCtx->uiDisplayHeight = vsinfo.yres;
88
89 DDI_NORMALMESSAGE("DDI:mediaDrvCtx->uiDisplayWidth =%d", mediaDrvCtx->uiDisplayWidth);
90 DDI_NORMALMESSAGE("DDI:mediaDrvCtx->uiDisplayHeight =%d",mediaDrvCtx->uiDisplayHeight);
91
92 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
93 {
94 DECODE_EVENTDATA_VA_DISPLAYINFO eventData;
95 eventData.uiDisplayWidth = mediaDrvCtx->uiDisplayWidth;
96 eventData.uiDisplayHeight = mediaDrvCtx->uiDisplayHeight;
97 MOS_TraceEvent(EVENT_DECODE_DDI_DISPLAYINFOVA, EVENT_TYPE_END, &eventData, sizeof(eventData), NULL, 0);
98 }
99 #endif
100 return 0;
101 }
102
DdiDecode_CreateBuffer(VADriverContextP ctx,PDDI_DECODE_CONTEXT decCtx,VABufferType type,uint32_t size,uint32_t numElements,void * data,VABufferID * bufId)103 VAStatus DdiDecode_CreateBuffer(
104 VADriverContextP ctx,
105 PDDI_DECODE_CONTEXT decCtx,
106 VABufferType type,
107 uint32_t size,
108 uint32_t numElements,
109 void *data,
110 VABufferID *bufId
111 )
112 {
113 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
114 {
115 MOS_TraceEvent(EVENT_DECODE_DDI_CREATEBUFFERVA, EVENT_TYPE_START, NULL, 0, NULL, 0);
116 }
117 #endif
118 *bufId = VA_INVALID_ID;
119 if (decCtx->m_ddiDecode){
120 DDI_CHK_RET(decCtx->m_ddiDecode->CreateBuffer(type, size, numElements, data, bufId),"DdiDecode_CreateBuffer failed!");
121 }
122
123 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
124 {
125 DECODE_EVENTDATA_VA_CREATEBUFFER eventData;
126 eventData.type = type;
127 eventData.size = size;
128 eventData.numElements = numElements;
129 eventData.bufId = bufId;
130 MOS_TraceEvent(EVENT_DECODE_DDI_CREATEBUFFERVA, EVENT_TYPE_END, &eventData, sizeof(eventData), NULL, 0);
131 }
132 #endif
133 return VA_STATUS_SUCCESS;
134
135 }
136
DdiDecode_BeginPicture(VADriverContextP ctx,VAContextID context,VASurfaceID renderTarget)137 VAStatus DdiDecode_BeginPicture (
138 VADriverContextP ctx,
139 VAContextID context,
140 VASurfaceID renderTarget
141 )
142 {
143 DDI_FUNCTION_ENTER();
144
145 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
146 {
147 DECODE_EVENTDATA_VA_BEGINPICTURE_START eventData;
148 eventData.FrameIndex = DecodeFrameIndex;
149 MOS_TraceEvent(EVENT_DECODE_DDI_BEGINPICTUREVA, EVENT_TYPE_START, &eventData, sizeof(eventData), NULL, 0);
150 }
151 #endif
152 PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_DDI);
153
154 uint32_t ctxType;
155 PDDI_DECODE_CONTEXT decCtx = (PDDI_DECODE_CONTEXT)DdiMedia_GetContextFromContextID(ctx, context, &ctxType);
156 DDI_CHK_NULL(decCtx, "nullptr decCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
157
158 if (decCtx->pCpDdiInterface)
159 {
160 DDI_CHK_RET(decCtx->pCpDdiInterface->IsAttachedSessionAlive(), "Session not alive!");
161 }
162
163 if (decCtx->m_ddiDecode)
164 {
165 VAStatus va = decCtx->m_ddiDecode->BeginPicture(ctx, context, renderTarget);
166 DDI_FUNCTION_EXIT(va);
167 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
168 {
169 DECODE_EVENTDATA_VA_BEGINPICTURE eventData;
170 eventData.FrameIndex = DecodeFrameIndex;
171 eventData.hRes = va;
172 MOS_TraceEvent(EVENT_DECODE_DDI_BEGINPICTUREVA, EVENT_TYPE_END, &eventData, sizeof(eventData), NULL, 0);
173 }
174 #endif
175 return va;
176 }
177
178 DDI_FUNCTION_EXIT(VA_STATUS_ERROR_UNIMPLEMENTED);
179 return VA_STATUS_ERROR_UNIMPLEMENTED;
180 }
181
182 /*
183 * Make the end of rendering for a picture.
184 * The server should start processing all pending operations for this
185 * surface. This call is non-blocking. The client can start another
186 * Begin/Render/End sequence on a different render target.
187 */
DdiDecode_EndPicture(VADriverContextP ctx,VAContextID context)188 VAStatus DdiDecode_EndPicture (
189 VADriverContextP ctx,
190 VAContextID context
191 )
192 {
193 DDI_FUNCTION_ENTER();
194
195 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
196 {
197 DECODE_EVENTDATA_VA_ENDPICTURE_START eventData;
198 eventData.FrameIndex = DecodeFrameIndex;
199 MOS_TraceEvent(EVENT_DECODE_DDI_ENDPICTUREVA, EVENT_TYPE_START, &eventData, sizeof(eventData), NULL, 0);
200 }
201 #endif
202 PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_DDI);
203
204 DDI_CHK_NULL(ctx, "nullptr context in vpgDecodeEndPicture!", VA_STATUS_ERROR_INVALID_CONTEXT);
205 uint32_t ctxType;
206 // assume the VAContextID is decoder ID
207 PDDI_DECODE_CONTEXT decCtx = (PDDI_DECODE_CONTEXT)DdiMedia_GetContextFromContextID(ctx, context, &ctxType);
208 DDI_CHK_NULL(decCtx, "nullptr decCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
209
210 if (decCtx->pCpDdiInterface)
211 {
212 DDI_CHK_RET(decCtx->pCpDdiInterface->IsAttachedSessionAlive(), "Session not alive!");
213
214 if (decCtx->pCpDdiInterface->IsCencProcessing())
215 {
216 VAStatus va = decCtx->pCpDdiInterface->EndPicture(ctx, context);
217 DDI_FUNCTION_EXIT(va);
218 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
219 {
220 DECODE_EVENTDATA_VA_ENDPICTURE eventData;
221 eventData.FrameIndex = DecodeFrameIndex;
222 eventData.hRes = va;
223 MOS_TraceEvent(EVENT_DECODE_DDI_ENDPICTUREVA, EVENT_TYPE_END, &eventData, sizeof(eventData), NULL, 0);
224 DecodeFrameIndex++;
225 }
226 #endif
227 return va;
228 }
229 }
230
231 if (decCtx->m_ddiDecode)
232 {
233 VAStatus va = decCtx->m_ddiDecode->EndPicture(ctx, context);
234 DDI_FUNCTION_EXIT(va);
235 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
236 {
237 DECODE_EVENTDATA_VA_ENDPICTURE eventData;
238 eventData.FrameIndex = DecodeFrameIndex;
239 eventData.hRes = va;
240 MOS_TraceEvent(EVENT_DECODE_DDI_ENDPICTUREVA, EVENT_TYPE_END, &eventData, sizeof(eventData), NULL, 0);
241 DecodeFrameIndex++;
242 }
243 #endif
244 return va;
245 }
246
247 DDI_FUNCTION_EXIT(VA_STATUS_ERROR_UNIMPLEMENTED);
248 return VA_STATUS_ERROR_UNIMPLEMENTED;
249 }
250
251 /*
252 * Send decode buffers to the server.
253 * Buffers are automatically destroyed afterwards
254 */
DdiDecode_RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)255 VAStatus DdiDecode_RenderPicture (
256 VADriverContextP ctx,
257 VAContextID context,
258 VABufferID *buffers,
259 int32_t numBuffers
260 )
261 {
262 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
263 {
264 DECODE_EVENTDATA_VA_RENDERPICTURE_START eventData;
265 eventData.buffers = buffers;
266 MOS_TraceEvent(EVENT_DECODE_DDI_RENDERPICTUREVA, EVENT_TYPE_START, &eventData, sizeof(eventData), NULL, 0);
267 }
268 #endif
269 VAStatus va = VA_STATUS_SUCCESS;
270 int32_t numOfBuffers = numBuffers;
271 int32_t priority = 0;
272 int32_t priorityIndexInBuffers = -1;
273 bool updatePriority = false;
274
275 DDI_FUNCTION_ENTER();
276
277 PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_DDI);
278
279 DDI_CHK_NULL(ctx, "nullptr context in vpgDecodeRenderPicture!", VA_STATUS_ERROR_INVALID_CONTEXT);
280 // assume the VAContextID is decoder ID
281 uint32_t ctxType;
282 PDDI_DECODE_CONTEXT decCtx = (PDDI_DECODE_CONTEXT)DdiMedia_GetContextFromContextID(ctx, context, &ctxType);
283 DDI_CHK_NULL(decCtx, "nullptr decCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
284
285 if (decCtx->pCpDdiInterface)
286 {
287 DDI_CHK_RET(decCtx->pCpDdiInterface->IsAttachedSessionAlive(), "Session not alive!");
288 }
289
290 priorityIndexInBuffers = DdiMedia_GetGpuPriority(ctx, buffers, numOfBuffers, &updatePriority, &priority);
291 if (priorityIndexInBuffers != -1)
292 {
293 if(updatePriority)
294 {
295 va = DdiDecode_SetGpuPriority(ctx, decCtx, priority);
296 if(va != VA_STATUS_SUCCESS)
297 return va;
298 }
299 MovePriorityBufferIdToEnd(buffers, priorityIndexInBuffers, numOfBuffers);
300 numOfBuffers--;
301 }
302 if (numOfBuffers == 0)
303 return va;
304
305 if (decCtx->m_ddiDecode)
306 {
307 va = decCtx->m_ddiDecode->RenderPicture(ctx, context, buffers, numOfBuffers);
308 DDI_FUNCTION_EXIT(va);
309 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
310 {
311 DECODE_EVENTDATA_VA_RENDERPICTURE eventData;
312 eventData.buffers = buffers;
313 eventData.hRes = va;
314 eventData.numBuffers = numBuffers;
315 MOS_TraceEvent(EVENT_DECODE_DDI_RENDERPICTUREVA, EVENT_TYPE_END, &eventData, sizeof(eventData), NULL, 0);
316 }
317 #endif
318 return va;
319 }
320
321 DDI_FUNCTION_EXIT(VA_STATUS_ERROR_UNIMPLEMENTED);
322 return VA_STATUS_ERROR_UNIMPLEMENTED;
323 }
324
325 //!
326 //! \brief Clean and free decode context structure.
327 //!
328 //! \param [in] ctx
329 //! Pointer to VA driver context
330 //! \param [in] decCtx
331 //! Pointer to ddi decode context
332 //!
DdiDecodeCleanUp(VADriverContextP ctx,PDDI_DECODE_CONTEXT decCtx)333 void DdiDecodeCleanUp(
334 VADriverContextP ctx,
335 PDDI_DECODE_CONTEXT decCtx)
336 {
337 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
338 {
339 MOS_TraceEvent(EVENT_DECODE_DDI_CLEARUPVA, EVENT_TYPE_START, NULL, 0, NULL, 0);
340 }
341 #endif
342 if(decCtx)
343 {
344 if(decCtx->m_ddiDecode)
345 {
346 decCtx->m_ddiDecode->DestroyContext(ctx);
347 MOS_Delete(decCtx->m_ddiDecode);
348 MOS_FreeMemory(decCtx);
349 decCtx = nullptr;
350 }
351 }
352 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
353 {
354 MOS_TraceEvent(EVENT_DECODE_DDI_CLEARUPVA, EVENT_TYPE_END, NULL, 0, NULL, 0);
355 }
356 #endif
357 return;
358 }
359
DdiDecode_StatusReport(PDDI_MEDIA_CONTEXT mediaCtx,CodechalDecode * decoder,DDI_MEDIA_SURFACE * surface)360 VAStatus DdiDecode_StatusReport(PDDI_MEDIA_CONTEXT mediaCtx, CodechalDecode *decoder, DDI_MEDIA_SURFACE *surface)
361 {
362 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
363 {
364 MOS_TraceEvent(EVENT_DECODE_DDI_STATUSREPORTVA, EVENT_TYPE_START, NULL, 0, NULL, 0);
365 }
366 #endif
367 if (decoder->IsStatusQueryReportingEnabled())
368 {
369 uint32_t i = 0;
370 if (surface->curStatusReportQueryState == DDI_MEDIA_STATUS_REPORT_QUERY_STATE_PENDING)
371 {
372 CodechalDecodeStatusBuffer *decodeStatusBuf = decoder->GetDecodeStatusBuf();
373 uint32_t uNumAvailableReport = (decodeStatusBuf->m_currIndex - decodeStatusBuf->m_firstIndex) & (CODECHAL_DECODE_STATUS_NUM - 1);
374 DDI_CHK_CONDITION((uNumAvailableReport == 0),
375 "No report available at all", VA_STATUS_ERROR_OPERATION_FAILED);
376
377 for (i = 0; i < uNumAvailableReport; i++)
378 {
379 int32_t index = (decodeStatusBuf->m_firstIndex + i) & (CODECHAL_DECODE_STATUS_NUM - 1);
380 if ((decodeStatusBuf->m_decodeStatus[index].m_decodeStatusReport.m_currDecodedPicRes.bo == surface->bo) ||
381 (decoder->GetStandard() == CODECHAL_VC1 && decodeStatusBuf->m_decodeStatus[index].m_decodeStatusReport.m_deblockedPicResOlp.bo == surface->bo))
382 {
383 break;
384 }
385 }
386
387 DDI_CHK_CONDITION((i == uNumAvailableReport),
388 "No report available for this surface", VA_STATUS_ERROR_OPERATION_FAILED);
389
390 uint32_t uNumCompletedReport = i+1;
391
392 for (i = 0; i < uNumCompletedReport; i++)
393 {
394 CodechalDecodeStatusReport tempNewReport;
395 MOS_ZeroMemory(&tempNewReport, sizeof(CodechalDecodeStatusReport));
396 MOS_STATUS eStatus = decoder->GetStatusReport(&tempNewReport, 1);
397 DDI_CHK_CONDITION(MOS_STATUS_SUCCESS != eStatus, "Get status report fail", VA_STATUS_ERROR_OPERATION_FAILED);
398
399 MOS_LINUX_BO *bo = tempNewReport.m_currDecodedPicRes.bo;
400
401 if (decoder->GetStandard() == CODECHAL_VC1)
402 {
403 bo = (tempNewReport.m_deblockedPicResOlp.bo) ? tempNewReport.m_deblockedPicResOlp.bo : bo;
404 }
405
406 if ((tempNewReport.m_codecStatus == CODECHAL_STATUS_SUCCESSFUL) ||
407 (tempNewReport.m_codecStatus == CODECHAL_STATUS_ERROR) ||
408 (tempNewReport.m_codecStatus == CODECHAL_STATUS_INCOMPLETE) ||
409 (tempNewReport.m_codecStatus == CODECHAL_STATUS_RESET))
410 {
411 PDDI_MEDIA_SURFACE_HEAP_ELEMENT mediaSurfaceHeapElmt = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)mediaCtx->pSurfaceHeap->pHeapBase;
412
413 uint32_t j = 0;
414 for (j = 0; j < mediaCtx->pSurfaceHeap->uiAllocatedHeapElements && mediaSurfaceHeapElmt != nullptr; j++, mediaSurfaceHeapElmt++)
415 {
416 if (mediaSurfaceHeapElmt->pSurface != nullptr && bo == mediaSurfaceHeapElmt->pSurface->bo)
417 {
418 mediaSurfaceHeapElmt->pSurface->curStatusReport.decode.status = (uint32_t)tempNewReport.m_codecStatus;
419 mediaSurfaceHeapElmt->pSurface->curStatusReport.decode.errMbNum = (uint32_t)tempNewReport.m_numMbsAffected;
420 mediaSurfaceHeapElmt->pSurface->curStatusReport.decode.crcValue = (decoder->GetStandard() == CODECHAL_AVC)?(uint32_t)tempNewReport.m_frameCrc:0;
421 mediaSurfaceHeapElmt->pSurface->curStatusReportQueryState = DDI_MEDIA_STATUS_REPORT_QUERY_STATE_COMPLETED;
422 break;
423 }
424 }
425 }
426 else
427 {
428 // return failed if queried INCOMPLETE or UNAVAILABLE report.
429 return VA_STATUS_ERROR_OPERATION_FAILED;
430 }
431 }
432 }
433
434 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
435 {
436 MOS_TraceEvent(EVENT_DECODE_DDI_STATUSREPORTVA, EVENT_TYPE_END, NULL, 0, NULL, 0);
437 }
438 #endif
439 // check the report ptr of current surface.
440 if (surface->curStatusReportQueryState == DDI_MEDIA_STATUS_REPORT_QUERY_STATE_COMPLETED)
441 {
442 if (surface->curStatusReport.decode.status == CODECHAL_STATUS_SUCCESSFUL)
443 {
444 return VA_STATUS_SUCCESS;
445 }
446 else if (surface->curStatusReport.decode.status == CODECHAL_STATUS_ERROR)
447 {
448 return VA_STATUS_ERROR_DECODING_ERROR;
449 }
450 else if (surface->curStatusReport.decode.status == CODECHAL_STATUS_INCOMPLETE ||
451 surface->curStatusReport.decode.status == CODECHAL_STATUS_RESET ||
452 surface->curStatusReport.decode.status == CODECHAL_STATUS_UNAVAILABLE)
453 {
454 return mediaCtx->bMediaResetEnable ? VA_STATUS_SUCCESS : VA_STATUS_ERROR_HW_BUSY;
455 }
456 }
457 else
458 {
459 return VA_STATUS_ERROR_OPERATION_FAILED;
460 }
461 }
462 return VA_STATUS_SUCCESS;
463 }
464
DdiDecode_StatusReport(PDDI_MEDIA_CONTEXT mediaCtx,DecodePipelineAdapter * decoder,DDI_MEDIA_SURFACE * surface)465 VAStatus DdiDecode_StatusReport(PDDI_MEDIA_CONTEXT mediaCtx, DecodePipelineAdapter *decoder, DDI_MEDIA_SURFACE *surface)
466 {
467 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
468 {
469 MOS_TraceEvent(EVENT_DECODE_DDI_STATUSREPORTVA, EVENT_TYPE_START, NULL, 0, NULL, 0);
470 }
471 #endif
472 if (surface->curStatusReportQueryState == DDI_MEDIA_STATUS_REPORT_QUERY_STATE_PENDING)
473 {
474 uint32_t uNumCompletedReport = decoder->GetCompletedReport();
475 if (uNumCompletedReport != 0)
476 {
477 for (uint32_t i = 0; i < uNumCompletedReport; i++)
478 {
479 decode::DecodeStatusReportData tempNewReport;
480 MOS_ZeroMemory(&tempNewReport, sizeof(CodechalDecodeStatusReport));
481 MOS_STATUS eStatus = decoder->GetStatusReport(&tempNewReport, 1);
482 DDI_CHK_CONDITION(MOS_STATUS_SUCCESS != eStatus, "Get status report fail", VA_STATUS_ERROR_OPERATION_FAILED);
483
484 MOS_LINUX_BO *bo = tempNewReport.currDecodedPicRes.bo;
485
486 if ((tempNewReport.codecStatus == CODECHAL_STATUS_SUCCESSFUL) ||
487 (tempNewReport.codecStatus == CODECHAL_STATUS_ERROR) ||
488 (tempNewReport.codecStatus == CODECHAL_STATUS_INCOMPLETE) ||
489 (tempNewReport.codecStatus == CODECHAL_STATUS_RESET))
490 {
491 PDDI_MEDIA_SURFACE_HEAP_ELEMENT mediaSurfaceHeapElmt = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)mediaCtx->pSurfaceHeap->pHeapBase;
492
493 uint32_t j = 0;
494 for (j = 0; j < mediaCtx->pSurfaceHeap->uiAllocatedHeapElements && mediaSurfaceHeapElmt != nullptr; j++, mediaSurfaceHeapElmt++)
495 {
496 if (mediaSurfaceHeapElmt->pSurface != nullptr && bo == mediaSurfaceHeapElmt->pSurface->bo)
497 {
498 mediaSurfaceHeapElmt->pSurface->curStatusReport.decode.status = (uint32_t)tempNewReport.codecStatus;
499 mediaSurfaceHeapElmt->pSurface->curStatusReport.decode.errMbNum = (uint32_t)tempNewReport.numMbsAffected;
500 mediaSurfaceHeapElmt->pSurface->curStatusReport.decode.crcValue = (uint32_t)tempNewReport.frameCrc;
501 mediaSurfaceHeapElmt->pSurface->curStatusReportQueryState = DDI_MEDIA_STATUS_REPORT_QUERY_STATE_COMPLETED;
502 break;
503 }
504 }
505 }
506 else
507 {
508 // return failed if queried INCOMPLETE or UNAVAILABLE report.
509 return VA_STATUS_ERROR_OPERATION_FAILED;
510 }
511 }
512 }
513 // The surface is not busy in HW, but uNumCompletedReport is 0, treat as engine reset
514 else
515 {
516 surface->curStatusReport.decode.status = CODECHAL_STATUS_INCOMPLETE;
517 surface->curStatusReportQueryState = DDI_MEDIA_STATUS_REPORT_QUERY_STATE_COMPLETED;
518 DDI_ASSERTMESSAGE("No report available at all! Engine reset may have occured.");
519 }
520 }
521
522 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
523 {
524 MOS_TraceEvent(EVENT_DECODE_DDI_STATUSREPORTVA, EVENT_TYPE_END, NULL, 0, NULL, 0);
525 }
526 #endif
527 // check the report ptr of current surface.
528 if (surface->curStatusReportQueryState == DDI_MEDIA_STATUS_REPORT_QUERY_STATE_COMPLETED)
529 {
530 if (surface->curStatusReport.decode.status == CODECHAL_STATUS_SUCCESSFUL)
531 {
532 return VA_STATUS_SUCCESS;
533 }
534 else if (surface->curStatusReport.decode.status == CODECHAL_STATUS_ERROR)
535 {
536 return VA_STATUS_ERROR_DECODING_ERROR;
537 }
538 else if (surface->curStatusReport.decode.status == CODECHAL_STATUS_INCOMPLETE ||
539 surface->curStatusReport.decode.status == CODECHAL_STATUS_RESET ||
540 surface->curStatusReport.decode.status == CODECHAL_STATUS_UNAVAILABLE)
541 {
542 return mediaCtx->bMediaResetEnable ? VA_STATUS_SUCCESS : VA_STATUS_ERROR_HW_BUSY;
543 }
544 }
545 else
546 {
547 return VA_STATUS_ERROR_OPERATION_FAILED;
548 }
549 return VA_STATUS_SUCCESS;
550 }
551
552 /*
553 * vpgDecodeCreateContext - Create a decode context
554 * dpy: display
555 * config_id: configuration for the context
556 * picture_width: coded picture width
557 * picture_height: coded picture height
558 * render_targets: render targets (surfaces) tied to the context
559 * num_render_targets: number of render targets in the above array
560 * context: created context id upon return
561 */
DdiDecode_CreateContext(VADriverContextP ctx,VAConfigID configId,int32_t pictureWidth,int32_t pictureHeight,int32_t flag,VASurfaceID * renderTargets,int32_t numRenderTargets,VAContextID * context)562 VAStatus DdiDecode_CreateContext (
563 VADriverContextP ctx,
564 VAConfigID configId,
565 int32_t pictureWidth,
566 int32_t pictureHeight,
567 int32_t flag,
568 VASurfaceID *renderTargets,
569 int32_t numRenderTargets,
570 VAContextID *context
571 )
572 {
573 PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_DDI);
574
575 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
576 {
577 DECODE_EVENTDATA_VA_CREATECONTEXT_START eventData;
578 eventData.configId = configId;
579 MOS_TraceEvent(EVENT_DECODE_DDI_CREATECONTEXTVA, EVENT_TYPE_START, &eventData, sizeof(eventData), NULL, 0);
580 }
581 #endif
582 MOS_CONTEXT mosCtx = {};
583 PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT contextHeapElement;
584 DdiMediaDecode *ddiDecBase;
585 DDI_DECODE_CONFIG_ATTR decConfigAttr;
586
587 DDI_UNUSED(flag);
588
589 VAStatus va = VA_STATUS_SUCCESS;
590 decConfigAttr.uiDecSliceMode = VA_DEC_SLICE_MODE_BASE;
591 *context = VA_INVALID_ID;
592
593 uint16_t mode = CODECHAL_DECODE_MODE_AVCVLD;
594
595 DDI_CHK_NULL(ctx, "nullptr Ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
596
597 PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
598 DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
599
600 PDDI_DECODE_CONTEXT decCtx = nullptr;
601 if (numRenderTargets > DDI_MEDIA_MAX_SURFACE_NUMBER_CONTEXT)
602 {
603 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
604 }
605
606 std::string codecKey = DECODE_ID_NONE;
607
608 DDI_CHK_NULL(mediaCtx->m_caps, "nullptr m_caps", VA_STATUS_ERROR_INVALID_CONTEXT);
609 DDI_CHK_RET(mediaCtx->m_caps->GetDecConfigAttr(
610 configId + DDI_CODEC_GEN_CONFIG_ATTRIBUTES_DEC_BASE,
611 &decConfigAttr.profile,
612 &decConfigAttr.entrypoint,
613 &decConfigAttr.uiDecSliceMode,
614 &decConfigAttr.uiEncryptionType,
615 &decConfigAttr.uiDecProcessingType),"Invalide config_id!");
616
617 mode = mediaCtx->m_caps->GetDecodeCodecMode(decConfigAttr.profile);
618 codecKey = mediaCtx->m_caps->GetDecodeCodecKey(decConfigAttr.profile);
619 va = mediaCtx->m_caps->CheckDecodeResolution(
620 mode,
621 decConfigAttr.profile,
622 pictureWidth,
623 pictureHeight);
624 if (va != VA_STATUS_SUCCESS)
625 {
626 DdiDecodeCleanUp(ctx,decCtx);
627 return va;
628 }
629
630 ddiDecBase = DdiDecodeFactory::CreateCodec(codecKey, nullptr);
631
632 if (ddiDecBase == nullptr)
633 {
634 DDI_ASSERTMESSAGE("DDI: failed to Create DecodeContext in vaCreateContext\n");
635 return VA_STATUS_ERROR_ALLOCATION_FAILED;
636 }
637
638 if (ddiDecBase->BasicInit(&decConfigAttr) != VA_STATUS_SUCCESS)
639 {
640 MOS_Delete(ddiDecBase);
641 return VA_STATUS_ERROR_ALLOCATION_FAILED;
642 }
643 /* one instance of DdiMediaDecode is created for the codec */
644 decCtx = (DDI_DECODE_CONTEXT *) (*ddiDecBase);
645
646 if (nullptr == decCtx)
647 {
648 if (ddiDecBase)
649 MOS_Delete(ddiDecBase);
650 return VA_STATUS_ERROR_ALLOCATION_FAILED;
651 }
652
653 decCtx->pMediaCtx = mediaCtx;
654 decCtx->m_ddiDecode = ddiDecBase;
655
656 mosCtx.bufmgr = mediaCtx->pDrmBufMgr;
657 mosCtx.m_gpuContextMgr = mediaCtx->m_gpuContextMgr;
658 mosCtx.m_cmdBufMgr = mediaCtx->m_cmdBufMgr;
659 mosCtx.fd = mediaCtx->fd;
660 mosCtx.iDeviceId = mediaCtx->iDeviceId;
661 mosCtx.m_skuTable = mediaCtx->SkuTable;
662 mosCtx.m_waTable = mediaCtx->WaTable;
663 mosCtx.m_gtSystemInfo = *mediaCtx->pGtSystemInfo;
664 mosCtx.m_platform = mediaCtx->platform;
665 mosCtx.ppMediaMemDecompState = &mediaCtx->pMediaMemDecompState;
666 mosCtx.pfnMemoryDecompress = mediaCtx->pfnMemoryDecompress;
667 mosCtx.pfnMediaMemoryCopy = mediaCtx->pfnMediaMemoryCopy;
668 mosCtx.pfnMediaMemoryCopy2D = mediaCtx->pfnMediaMemoryCopy2D;
669 mosCtx.ppMediaCopyState = &mediaCtx->pMediaCopyState;
670 mosCtx.m_auxTableMgr = mediaCtx->m_auxTableMgr;
671 mosCtx.pGmmClientContext = mediaCtx->pGmmClientContext;
672 mosCtx.m_osDeviceContext = mediaCtx->m_osDeviceContext;
673 mosCtx.m_apoMosEnabled = mediaCtx->m_apoMosEnabled;
674 mosCtx.pPerfData = (PERF_DATA *)MOS_AllocAndZeroMemory(sizeof(PERF_DATA));
675 mosCtx.m_userSettingPtr = mediaCtx->m_userSettingPtr;
676
677 if (nullptr == mosCtx.pPerfData)
678 {
679 va = VA_STATUS_ERROR_ALLOCATION_FAILED;
680 DdiDecodeCleanUp(ctx, decCtx);
681 return va;
682 }
683
684 ddiDecBase->ContextInit(pictureWidth, pictureHeight);
685
686 //initialize DDI level CP interface
687 decCtx->pCpDdiInterface = Create_DdiCpInterface(mosCtx);
688 if (nullptr == decCtx->pCpDdiInterface)
689 {
690 va = VA_STATUS_ERROR_ALLOCATION_FAILED;
691 DdiDecodeCleanUp(ctx,decCtx);
692 return va;
693 }
694
695 /* the step three */
696 va = ddiDecBase->CodecHalInit(mediaCtx, &mosCtx);
697 if (va != VA_STATUS_SUCCESS)
698 {
699 DdiDecodeCleanUp(ctx,decCtx);
700 return va;
701 }
702
703 DdiDecode_GetDisplayInfo(ctx);
704
705 // register render targets
706 for (int32_t i = 0; i < numRenderTargets; i++)
707 {
708 DDI_MEDIA_SURFACE *surface;
709
710 surface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, renderTargets[i]);
711 if (nullptr == surface)
712 {
713 DDI_ASSERTMESSAGE("DDI: invalid render target %d in vpgCreateContext.",i);
714 va = VA_STATUS_ERROR_INVALID_SURFACE;
715 DdiDecodeCleanUp(ctx,decCtx);
716 return va;
717 }
718 if (VA_STATUS_SUCCESS != ddiDecBase->RegisterRTSurfaces(&decCtx->RTtbl, surface))
719 {
720 va = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
721 DdiDecodeCleanUp(ctx,decCtx);
722 return va;
723 }
724 }
725
726 DdiMediaUtil_LockMutex(&mediaCtx->DecoderMutex);
727 contextHeapElement = DdiMediaUtil_AllocPVAContextFromHeap(mediaCtx->pDecoderCtxHeap);
728
729 if (nullptr == contextHeapElement)
730 {
731 DdiMediaUtil_UnLockMutex(&mediaCtx->DecoderMutex);
732 va = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
733 DdiDecodeCleanUp(ctx,decCtx);
734 return va;
735 }
736
737 contextHeapElement->pVaContext = (void*)decCtx;
738 mediaCtx->uiNumDecoders++;
739 *context = (VAContextID)(contextHeapElement->uiVaContextID + DDI_MEDIA_VACONTEXTID_OFFSET_DECODER);
740 DdiMediaUtil_UnLockMutex(&mediaCtx->DecoderMutex);
741
742 // init the RecListSUrfaceID for checking DPB.
743 for(int32_t i = 0; i < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE; i++)
744 {
745 decCtx->RecListSurfaceID[i] = VA_INVALID_ID;
746 }
747 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
748 {
749 DECODE_EVENTDATA_VA_CREATECONTEXT eventData;
750 eventData.configId = configId;
751 eventData.hRes = va;
752 MOS_TraceEvent(EVENT_DECODE_DDI_CREATECONTEXTVA, EVENT_TYPE_END, &eventData, sizeof(eventData), NULL, 0);
753 }
754 #endif
755 return va;
756 }
757
758
759 //!
760 //! \brief Get ctx from VA buffer ID
761 //!
762 //! \param [in] mediaCtx
763 //! pddi media context
764 //! \param [in] bufferID
765 //! VA Buffer ID
766 //!
767 //! \return void*
768 //! Pointer to buffer heap element context
769 //!
DdiMedia_GetDecCtxFromVABufferID(PDDI_MEDIA_CONTEXT mediaCtx,VABufferID bufferID)770 static void* DdiMedia_GetDecCtxFromVABufferID (PDDI_MEDIA_CONTEXT mediaCtx, VABufferID bufferID)
771 {
772 DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", nullptr);
773
774 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
775 {
776 MOS_TraceEvent(EVENT_DECODE_DDI_GETDECCTXFROMBUFFERIDVA, EVENT_TYPE_START, NULL, 0, NULL, 0);
777 }
778 #endif
779 uint32_t i = (uint32_t)bufferID;
780 DDI_CHK_LESS(i, mediaCtx->pBufferHeap->uiAllocatedHeapElements, "invalid buffer id", nullptr);
781 DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
782 PDDI_MEDIA_BUFFER_HEAP_ELEMENT bufHeapElement = (PDDI_MEDIA_BUFFER_HEAP_ELEMENT)mediaCtx->pBufferHeap->pHeapBase;
783 bufHeapElement += i;
784 void *temp = bufHeapElement->pCtx;
785 DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
786
787 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
788 {
789 DECODE_EVENTDATA_VA_GETDECCTX eventData;
790 eventData.bufferID = (uint32_t)bufferID;
791 MOS_TraceEvent(EVENT_DECODE_DDI_GETDECCTXFROMBUFFERIDVA, EVENT_TYPE_END, &eventData, sizeof(eventData), NULL, 0);
792 }
793 #endif
794 return temp;
795 }
796
797
798 /////////////////////////////////////////////////////////////////////////////
799 //! \Free allocated bufferheap elements
800 //! \params
801 //! [in] VADriverContextP
802 //! [out] none
803 //! \returns
804 /////////////////////////////////////////////////////////////////////////////
DdiMedia_FreeBufferHeapElements(VADriverContextP ctx,PDDI_DECODE_CONTEXT decCtx)805 static void DdiMedia_FreeBufferHeapElements(VADriverContextP ctx, PDDI_DECODE_CONTEXT decCtx)
806 {
807 PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
808 if (nullptr == mediaCtx)
809 return;
810
811 PDDI_MEDIA_HEAP bufferHeap = mediaCtx->pBufferHeap;
812 if (nullptr == bufferHeap)
813 return;
814
815 PDDI_MEDIA_BUFFER_HEAP_ELEMENT mediaBufferHeapBase = (PDDI_MEDIA_BUFFER_HEAP_ELEMENT)bufferHeap->pHeapBase;
816 if (nullptr == mediaBufferHeapBase)
817 return;
818
819 int32_t bufNums = mediaCtx->uiNumBufs;
820 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
821 {
822 DECODE_EVENTDATA_VA_FREEBUFFERHEAPELEMENTS eventData;
823 eventData.bufNums = bufNums;
824 MOS_TraceEvent(EVENT_DECODE_DDI_FREEBUFFERHEAPELEMENTSVA, EVENT_TYPE_START, &eventData, sizeof(eventData), NULL, 0);
825 }
826 #endif
827 for (int32_t elementId = 0; bufNums > 0 && elementId < bufferHeap->uiAllocatedHeapElements; ++elementId)
828 {
829 PDDI_MEDIA_BUFFER_HEAP_ELEMENT mediaBufferHeapElmt = &mediaBufferHeapBase[elementId];
830 if (nullptr == mediaBufferHeapElmt->pBuffer)
831 continue;
832
833 void *pDecContext =DdiMedia_GetDecCtxFromVABufferID(mediaCtx, mediaBufferHeapElmt->uiVaBufferID);
834 if(pDecContext == decCtx)
835 {
836 DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, mediaBufferHeapElmt->uiVaBufferID);
837
838 if (nullptr == buf)
839 {
840 return;
841 }
842
843 if(buf->uiType == VASliceDataBufferType ||
844 buf->uiType == VAProtectedSliceDataBufferType ||
845 buf->uiType == VASliceParameterBufferType)
846 {
847 DdiMedia_DestroyBuffer(ctx, mediaBufferHeapElmt->uiVaBufferID);
848 }
849 }
850 //Ensure the non-empty buffer to be destroyed.
851 --bufNums;
852 }
853 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
854 {
855 DECODE_EVENTDATA_VA_FREEBUFFERHEAPELEMENTS eventData;
856 eventData.bufNums = bufNums;
857 MOS_TraceEvent(EVENT_DECODE_DDI_FREEBUFFERHEAPELEMENTSVA, EVENT_TYPE_END, &eventData, sizeof(eventData), NULL, 0);
858 }
859 #endif
860 }
861
DdiDecode_DestroyContext(VADriverContextP ctx,VAContextID context)862 VAStatus DdiDecode_DestroyContext (
863 VADriverContextP ctx,
864 VAContextID context
865 )
866 {
867 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
868 {
869 DECODE_EVENTDATA_VA_DESTROYCONTEXT_START eventData;
870 eventData.context = context;
871 MOS_TraceEvent(EVENT_DECODE_DDI_DESTROYCONTEXTVA, EVENT_TYPE_START, &eventData, sizeof(eventData), NULL, 0);
872 }
873 #endif
874 PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
875 DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
876 uint32_t ctxType;
877 PDDI_DECODE_CONTEXT decCtx = (PDDI_DECODE_CONTEXT)DdiMedia_GetContextFromContextID(ctx, context, &ctxType);
878 DDI_CHK_NULL(decCtx, "nullptr decCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
879 DDI_CHK_NULL(decCtx->pCodecHal, "nullptr decCtx->pCodecHal", VA_STATUS_ERROR_INVALID_CONTEXT);
880
881 /* Free the context id from the context_heap earlier */
882 uint32_t decIndex = (uint32_t)context & DDI_MEDIA_MASK_VACONTEXTID;
883 DdiMediaUtil_LockMutex(&mediaCtx->DecoderMutex);
884 DdiMediaUtil_ReleasePVAContextFromHeap(mediaCtx->pDecoderCtxHeap, decIndex);
885 mediaCtx->uiNumDecoders--;
886 DdiMediaUtil_UnLockMutex(&mediaCtx->DecoderMutex);
887
888 DdiMedia_FreeBufferHeapElements(ctx, decCtx);
889
890 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
891 {
892 DECODE_EVENTDATA_VA_DESTROYCONTEXT eventData;
893 eventData.context = context;
894 MOS_TraceEvent(EVENT_DECODE_DDI_DESTROYCONTEXTVA, EVENT_TYPE_END, &eventData, sizeof(eventData), NULL, 0);
895 }
896 #endif
897 if (decCtx->m_ddiDecode) {
898 DdiDecodeCleanUp(ctx,decCtx);
899 return VA_STATUS_SUCCESS;
900 }
901
902 return VA_STATUS_SUCCESS;
903 }
904
DdiDecode_SetGpuPriority(VADriverContextP ctx,PDDI_DECODE_CONTEXT decCtx,int32_t priority)905 VAStatus DdiDecode_SetGpuPriority(
906 VADriverContextP ctx,
907 PDDI_DECODE_CONTEXT decCtx,
908 int32_t priority
909 )
910 {
911 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
912 {
913 MOS_TraceEvent(EVENT_DECODE_DDI_SETGPUPRIORITYVA, EVENT_TYPE_START, NULL, 0, NULL, 0);
914 }
915 #endif
916 PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
917 DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
918 DDI_CHK_NULL(decCtx, "nullptr decCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
919
920 //Set the priority for Gpu
921 if(decCtx->pCodecHal != nullptr)
922 {
923 PMOS_INTERFACE osInterface = decCtx->pCodecHal->GetOsInterface();
924 DDI_CHK_NULL(osInterface, "nullptr osInterface.", VA_STATUS_ERROR_ALLOCATION_FAILED);
925 osInterface->pfnSetGpuPriority(osInterface, priority);
926 }
927 #ifdef _MMC_SUPPORTED
928 //set the priority for decomp interface
929 if(mediaCtx->pMediaMemDecompState)
930 {
931 MediaVeboxDecompState *mediaVeboxDecompState = static_cast<MediaVeboxDecompState*>(mediaCtx->pMediaMemDecompState);
932 if(mediaVeboxDecompState->m_osInterface)
933 mediaVeboxDecompState->m_osInterface->pfnSetGpuPriority(mediaVeboxDecompState->m_osInterface, priority);
934 }
935 #endif
936 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
937 {
938 MOS_TraceEvent(EVENT_DECODE_DDI_SETGPUPRIORITYVA, EVENT_TYPE_END, NULL, 0, NULL, 0);
939 }
940 #endif
941 return VA_STATUS_SUCCESS;
942 }
943
944