1 /*
2 * Copyright (c) 2015-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 //! \file media_libva_common.cpp
23 //! \brief libva(and its extension) interface implemantation common functions
24 //!
25
26 #include "media_libva.h"
27 #include "media_libva_util.h"
28 #include "media_ddi_prot.h"
29 #include "mos_solo_generic.h"
30 #include "mos_interface.h"
31 #include "media_libva_caps.h"
32
DdiMedia_GetVaContextFromHeap(PDDI_MEDIA_HEAP mediaHeap,uint32_t index,PMEDIA_MUTEX_T mutex)33 static void* DdiMedia_GetVaContextFromHeap(PDDI_MEDIA_HEAP mediaHeap, uint32_t index, PMEDIA_MUTEX_T mutex)
34 {
35 PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT vaCtxHeapElmt = nullptr;
36 void *context = nullptr;
37
38 DdiMediaUtil_LockMutex(mutex);
39 if(nullptr == mediaHeap || index >= mediaHeap->uiAllocatedHeapElements)
40 {
41 DdiMediaUtil_UnLockMutex(mutex);
42 return nullptr;
43 }
44 vaCtxHeapElmt = (PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT)mediaHeap->pHeapBase;
45 vaCtxHeapElmt += index;
46 context = vaCtxHeapElmt->pVaContext;
47 DdiMediaUtil_UnLockMutex(mutex);
48
49 return context;
50 }
51
DdiMedia_MediaSurfaceToMosResource(DDI_MEDIA_SURFACE * mediaSurface,MOS_RESOURCE * mosResource)52 void DdiMedia_MediaSurfaceToMosResource(DDI_MEDIA_SURFACE *mediaSurface, MOS_RESOURCE *mosResource)
53 {
54 DDI_CHK_NULL(mediaSurface, "nullptr mediaSurface",);
55 DDI_CHK_NULL(mosResource, "nullptr mosResource",);
56 DDI_ASSERT(mosResource->bo);
57
58 MosInterface::ConvertResourceFromDdi(mediaSurface, mosResource, OS_SPECIFIC_RESOURCE_SURFACE, 0);
59
60 Mos_Solo_SetOsResource(mediaSurface->pGmmResourceInfo, mosResource);
61
62 return;
63 }
64
DdiMedia_MediaBufferToMosResource(DDI_MEDIA_BUFFER * mediaBuffer,MOS_RESOURCE * mosResource)65 void DdiMedia_MediaBufferToMosResource(DDI_MEDIA_BUFFER *mediaBuffer, MOS_RESOURCE *mosResource)
66 {
67 DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer",);
68 DDI_CHK_NULL(mosResource, "nullptr mosResource",);
69 DDI_ASSERT(mediaBuffer->bo);
70
71 MosInterface::ConvertResourceFromDdi(mediaBuffer, mosResource, OS_SPECIFIC_RESOURCE_BUFFER, 0);
72
73 Mos_Solo_SetOsResource(mediaBuffer->pGmmResourceInfo, mosResource);
74
75 return;
76 }
77
DdiMedia_GetContextFromContextID(VADriverContextP ctx,VAContextID vaCtxID,uint32_t * ctxType)78 void* DdiMedia_GetContextFromContextID (VADriverContextP ctx, VAContextID vaCtxID, uint32_t *ctxType)
79 {
80 PDDI_MEDIA_CONTEXT mediaCtx = nullptr;
81 uint32_t index = 0;
82
83 DDI_CHK_NULL(ctx, "nullptr ctx", nullptr);
84 DDI_CHK_NULL(ctxType, "nullptr ctxType", nullptr);
85
86 mediaCtx = DdiMedia_GetMediaContext(ctx);
87 index = vaCtxID & DDI_MEDIA_MASK_VACONTEXTID;
88
89 if (index >= DDI_MEDIA_MAX_INSTANCE_NUMBER)
90 return nullptr;
91 if ((vaCtxID&DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_PROT)
92 {
93 DDI_VERBOSEMESSAGE("Protected session detected: 0x%x", vaCtxID);
94 *ctxType = DDI_MEDIA_CONTEXT_TYPE_PROTECTED;
95 index = index & DDI_MEDIA_MASK_VAPROTECTEDSESSION_ID;
96 return DdiMedia_GetVaContextFromHeap(mediaCtx->pProtCtxHeap, index, &mediaCtx->ProtMutex);
97 }
98 else if ((vaCtxID&DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_DECODER)
99 {
100 DDI_VERBOSEMESSAGE("Decode context detected: 0x%x", vaCtxID);
101 *ctxType = DDI_MEDIA_CONTEXT_TYPE_DECODER;
102 return DdiMedia_GetVaContextFromHeap(mediaCtx->pDecoderCtxHeap, index, &mediaCtx->DecoderMutex);
103 }
104 else if ((vaCtxID&DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_ENCODER)
105 {
106 *ctxType = DDI_MEDIA_CONTEXT_TYPE_ENCODER;
107 return DdiMedia_GetVaContextFromHeap(mediaCtx->pEncoderCtxHeap, index, &mediaCtx->EncoderMutex);
108 }
109 else if ((vaCtxID & DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_VP)
110 {
111 *ctxType = DDI_MEDIA_CONTEXT_TYPE_VP;
112 return DdiMedia_GetVaContextFromHeap(mediaCtx->pVpCtxHeap, index, &mediaCtx->VpMutex);
113 }
114 else if ((vaCtxID & DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_CM)
115 {
116 *ctxType = DDI_MEDIA_CONTEXT_TYPE_CM;
117 return DdiMedia_GetVaContextFromHeap(mediaCtx->pCmCtxHeap, index, &mediaCtx->CmMutex);
118 }
119 else if ((vaCtxID & DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_MFE)
120 {
121 *ctxType = DDI_MEDIA_CONTEXT_TYPE_MFE;
122 return DdiMedia_GetVaContextFromHeap(mediaCtx->pMfeCtxHeap, index, &mediaCtx->MfeMutex);
123 }
124 else
125 {
126 DDI_ASSERTMESSAGE("Invalid context: 0x%x", vaCtxID);
127 *ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
128 return nullptr;
129 }
130
131 }
132
DdiMedia_GetSurfaceFromVASurfaceID(PDDI_MEDIA_CONTEXT mediaCtx,VASurfaceID surfaceID)133 DDI_MEDIA_SURFACE* DdiMedia_GetSurfaceFromVASurfaceID (PDDI_MEDIA_CONTEXT mediaCtx, VASurfaceID surfaceID)
134 {
135 uint32_t i = 0;
136 PDDI_MEDIA_SURFACE_HEAP_ELEMENT surfaceElement = nullptr;
137 PDDI_MEDIA_SURFACE surface = nullptr;
138
139 DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", nullptr);
140
141 i = (uint32_t)surfaceID;
142 bool validSurface = (i != VA_INVALID_SURFACE);
143 if(validSurface)
144 {
145 DDI_CHK_LESS(i, mediaCtx->pSurfaceHeap->uiAllocatedHeapElements, "invalid surface id", nullptr);
146 DdiMediaUtil_LockMutex(&mediaCtx->SurfaceMutex);
147 surfaceElement = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)mediaCtx->pSurfaceHeap->pHeapBase;
148 surfaceElement += i;
149 surface = surfaceElement->pSurface;
150 DdiMediaUtil_UnLockMutex(&mediaCtx->SurfaceMutex);
151 }
152
153 return surface;
154 }
155
DdiMedia_GetVASurfaceIDFromSurface(PDDI_MEDIA_SURFACE surface)156 VASurfaceID DdiMedia_GetVASurfaceIDFromSurface(PDDI_MEDIA_SURFACE surface)
157 {
158 DDI_CHK_NULL(surface, "nullptr surface", VA_INVALID_SURFACE);
159
160 PDDI_MEDIA_SURFACE_HEAP_ELEMENT surfaceElement = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)surface->pMediaCtx->pSurfaceHeap->pHeapBase;
161 for(uint32_t i = 0; i < surface->pMediaCtx->pSurfaceHeap->uiAllocatedHeapElements; i ++)
162 {
163 if(surface == surfaceElement->pSurface)
164 {
165 return surfaceElement->uiVaSurfaceID;
166 }
167 surfaceElement ++;
168 }
169 return VA_INVALID_SURFACE;
170 }
171
DdiMedia_ReplaceSurfaceWithNewFormat(PDDI_MEDIA_SURFACE surface,DDI_MEDIA_FORMAT expectedFormat)172 PDDI_MEDIA_SURFACE DdiMedia_ReplaceSurfaceWithNewFormat(PDDI_MEDIA_SURFACE surface, DDI_MEDIA_FORMAT expectedFormat)
173 {
174 DDI_CHK_NULL(surface, "nullptr surface", nullptr);
175
176 PDDI_MEDIA_SURFACE_HEAP_ELEMENT surfaceElement = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)surface->pMediaCtx->pSurfaceHeap->pHeapBase;
177 PDDI_MEDIA_CONTEXT mediaCtx = surface->pMediaCtx;
178
179 //check some conditions
180 if(expectedFormat == surface->format)
181 {
182 return surface;
183 }
184 //create new dst surface and copy the structure
185 PDDI_MEDIA_SURFACE dstSurface = (DDI_MEDIA_SURFACE *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_SURFACE));
186 if (nullptr == surfaceElement)
187 {
188 MOS_FreeMemory(dstSurface);
189 return nullptr;
190 }
191
192 MOS_SecureMemcpy(dstSurface,sizeof(DDI_MEDIA_SURFACE),surface,sizeof(DDI_MEDIA_SURFACE));
193 DDI_CHK_NULL(dstSurface, "nullptr dstSurface", nullptr);
194 dstSurface->format = expectedFormat;
195 dstSurface->uiLockedBufID = VA_INVALID_ID;
196 dstSurface->uiLockedImageID = VA_INVALID_ID;
197 dstSurface->pSurfDesc = nullptr;
198 //lock surface heap
199 DdiMediaUtil_LockMutex(&mediaCtx->SurfaceMutex);
200 uint32_t i;
201 //get current element heap and index
202 for(i = 0; i < mediaCtx->pSurfaceHeap->uiAllocatedHeapElements; i ++)
203 {
204 if(surface == surfaceElement->pSurface)
205 {
206 break;
207 }
208 surfaceElement ++;
209 }
210 //if cant find
211 if(i == surface->pMediaCtx->pSurfaceHeap->uiAllocatedHeapElements)
212 {
213 DdiMediaUtil_LockMutex(&mediaCtx->SurfaceMutex);
214 MOS_FreeMemory(dstSurface);
215 return nullptr;
216 }
217 //FreeSurface
218 DdiMediaUtil_FreeSurface(surface);
219 MOS_FreeMemory(surface);
220 //CreateNewSurface
221 DdiMediaUtil_CreateSurface(dstSurface,mediaCtx);
222 surfaceElement->pSurface = dstSurface;
223
224 DdiMediaUtil_UnLockMutex(&mediaCtx->SurfaceMutex);
225
226 return dstSurface;
227 }
228
DdiMedia_ReplaceSurfaceWithVariant(PDDI_MEDIA_SURFACE surface,VAEntrypoint entrypoint)229 PDDI_MEDIA_SURFACE DdiMedia_ReplaceSurfaceWithVariant(PDDI_MEDIA_SURFACE surface, VAEntrypoint entrypoint)
230 {
231 DDI_CHK_NULL(surface, "nullptr surface", nullptr);
232
233 PDDI_MEDIA_CONTEXT mediaCtx = surface->pMediaCtx;
234 uint32_t aligned_width, aligned_height;
235 DDI_MEDIA_FORMAT aligned_format;
236
237 //check some conditions
238 if(surface->uiVariantFlag)
239 {
240 return surface;
241 }
242
243 VASurfaceID vaID = DdiMedia_GetVASurfaceIDFromSurface(surface);
244 if(VA_INVALID_SURFACE == vaID)
245 {
246 return nullptr;
247 }
248
249 DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
250 PDDI_MEDIA_SURFACE_HEAP_ELEMENT surfaceElement = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)surface->pMediaCtx->pSurfaceHeap->pHeapBase;
251 DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
252 if (nullptr == surfaceElement)
253 {
254 return nullptr;
255 }
256 DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
257 surfaceElement += vaID;
258 DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
259
260 aligned_format = surface->format;
261 switch (surface->format)
262 {
263 case Media_Format_AYUV:
264 #if VA_CHECK_VERSION(1, 13, 0)
265 case Media_Format_XYUV:
266 #endif
267 aligned_width = MOS_ALIGN_CEIL(surface->iWidth, 128);
268 aligned_height = MOS_ALIGN_CEIL(surface->iHeight * 3 / 4, 64);
269 break;
270 case Media_Format_Y410:
271 aligned_width = MOS_ALIGN_CEIL(surface->iWidth, 64);
272 aligned_height = MOS_ALIGN_CEIL(surface->iHeight * 3 / 2, 64);
273 break;
274 case Media_Format_Y216:
275 #if VA_CHECK_VERSION(1, 9, 0)
276 case Media_Format_Y212:
277 #endif
278 case Media_Format_Y210:
279 aligned_width = (surface->iWidth + 1) >> 1;
280 aligned_height = surface->iHeight * 2;
281 aligned_format = Media_Format_Y216;
282 break;
283 case Media_Format_YUY2:
284 aligned_width = (surface->iWidth + 1) >> 1;
285 aligned_height = surface->iHeight * 2;
286 break;
287 case Media_Format_P016:
288 case Media_Format_P012:
289 case Media_Format_P010:
290 aligned_height = surface->iHeight;
291 aligned_width = surface->iWidth;
292 if(entrypoint == VAEntrypointEncSlice)
293 {
294 aligned_width = surface->iWidth * 2;
295 aligned_format = Media_Format_NV12;
296 }
297 else
298 {
299 aligned_format = Media_Format_P016;
300 }
301 break;
302 default:
303 return surface;
304 }
305
306 //create new dst surface and copy the structure
307 PDDI_MEDIA_SURFACE dstSurface = (DDI_MEDIA_SURFACE *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_SURFACE));
308
309 MOS_SecureMemcpy(dstSurface,sizeof(DDI_MEDIA_SURFACE),surface,sizeof(DDI_MEDIA_SURFACE));
310 DDI_CHK_NULL(dstSurface, "nullptr dstSurface", nullptr);
311
312 dstSurface->uiVariantFlag = 1;
313 dstSurface->format = aligned_format;
314 dstSurface->iWidth = aligned_width;
315 dstSurface->iHeight = aligned_height;
316 //CreateNewSurface
317 if(DdiMediaUtil_CreateSurface(dstSurface,mediaCtx) != VA_STATUS_SUCCESS)
318 {
319 MOS_FreeMemory(dstSurface);
320 return surface;
321 }
322 //replace the surface
323 DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
324 surfaceElement = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)surface->pMediaCtx->pSurfaceHeap->pHeapBase;
325 surfaceElement += vaID;
326 surfaceElement->pSurface = dstSurface;
327 DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
328 //FreeSurface
329 DdiMediaUtil_FreeSurface(surface);
330 MOS_FreeMemory(surface);
331
332 return dstSurface;
333 }
334
DdiMedia_GetBufferFromVABufferID(PDDI_MEDIA_CONTEXT mediaCtx,VABufferID bufferID)335 DDI_MEDIA_BUFFER* DdiMedia_GetBufferFromVABufferID (PDDI_MEDIA_CONTEXT mediaCtx, VABufferID bufferID)
336 {
337 uint32_t i = 0;
338 PDDI_MEDIA_BUFFER_HEAP_ELEMENT bufHeapElement = nullptr;
339 PDDI_MEDIA_BUFFER buf = nullptr;
340
341 i = (uint32_t)bufferID;
342 DDI_CHK_LESS(i, mediaCtx->pBufferHeap->uiAllocatedHeapElements, "invalid buffer id", nullptr);
343 DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
344 bufHeapElement = (PDDI_MEDIA_BUFFER_HEAP_ELEMENT)mediaCtx->pBufferHeap->pHeapBase;
345 bufHeapElement += i;
346 buf = bufHeapElement->pBuffer;
347 DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
348
349 return buf;
350 }
351
DdiMedia_DestroyBufFromVABufferID(PDDI_MEDIA_CONTEXT mediaCtx,VABufferID bufferID)352 bool DdiMedia_DestroyBufFromVABufferID (PDDI_MEDIA_CONTEXT mediaCtx, VABufferID bufferID)
353 {
354 DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
355 DdiMediaUtil_ReleasePMediaBufferFromHeap(mediaCtx->pBufferHeap, bufferID);
356 mediaCtx->uiNumBufs--;
357 DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
358 return true;
359 }
360
DdiMedia_GetContextFromVABufferID(PDDI_MEDIA_CONTEXT mediaCtx,VABufferID bufferID)361 void* DdiMedia_GetContextFromVABufferID (PDDI_MEDIA_CONTEXT mediaCtx, VABufferID bufferID)
362 {
363 uint32_t i;
364 PDDI_MEDIA_BUFFER_HEAP_ELEMENT bufHeapElement;
365 void * ctx;
366
367 i = (uint32_t)bufferID;
368 DDI_CHK_LESS(i, mediaCtx->pBufferHeap->uiAllocatedHeapElements, "invalid buffer id", nullptr);
369 DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
370 bufHeapElement = (PDDI_MEDIA_BUFFER_HEAP_ELEMENT)mediaCtx->pBufferHeap->pHeapBase;
371 bufHeapElement += bufferID;
372 ctx = bufHeapElement->pCtx;
373 DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
374
375 return ctx;
376 }
377
DdiMedia_GetGpuPriority(VADriverContextP ctx,VABufferID * buffers,int32_t numBuffers,bool * updatePriority,int32_t * priority)378 int32_t DdiMedia_GetGpuPriority (VADriverContextP ctx, VABufferID *buffers, int32_t numBuffers, bool *updatePriority, int32_t *priority)
379 {
380 void * data;
381 uint32_t updateSessionPriority = 0;
382 uint32_t priorityValue = 0;
383 int32_t priorityIndexInBuf = -1;
384
385 DDI_CHK_NULL(ctx, "nullptr context in DdiMedia_GetGpuPriority!", -1);
386
387 PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
388 DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", -1);
389 #if VA_CHECK_VERSION(1, 10, 0)
390 for (int32_t i = 0; i < numBuffers; i++)
391 {
392 DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
393 DDI_CHK_NULL(buf, "Invalid buffer.", -1);
394
395 if((int32_t)buf->uiType == VAContextParameterUpdateBufferType)
396 {
397 //Read the priority from the VAContextParameterUpdateBuffer
398 DdiMedia_MapBuffer(ctx, buffers[i], &data);
399 DDI_CHK_NULL(data, "nullptr data.", -1);
400
401 VAContextParameterUpdateBuffer *ContextParamBuf = (VAContextParameterUpdateBuffer *)data;
402 DDI_CHK_NULL(ContextParamBuf, "nullptr ContextParamBuf.", -1);
403
404 updateSessionPriority = ContextParamBuf->flags.bits.context_priority_update;
405 priorityValue = ContextParamBuf->context_priority.bits.priority;
406
407 if (updateSessionPriority)
408 {
409 *updatePriority = true;
410 if(priorityValue >= 0 && priorityValue <= CONTEXT_PRIORITY_MAX)
411 {
412 *priority = priorityValue - CONTEXT_PRIORITY_MAX/2;
413 }
414 else
415 {
416 *priority = 0;
417 }
418 }
419 else
420 {
421 *updatePriority = false;
422 *priority = 0;
423 }
424
425 DdiMedia_UnmapBuffer(ctx, buffers[i]);
426 priorityIndexInBuf = i;
427 break;
428 }
429 }
430 #endif
431 return priorityIndexInBuf;
432 }
433
434 //Move the priority bufferID to the end of buffers
MovePriorityBufferIdToEnd(VABufferID * buffers,int32_t priorityIndexInBuf,int32_t numBuffers)435 void MovePriorityBufferIdToEnd (VABufferID *buffers, int32_t priorityIndexInBuf, int32_t numBuffers)
436 {
437 VABufferID vaBufferID = 0;
438 if( (numBuffers > 1) && (priorityIndexInBuf < numBuffers -1) )
439 {
440 vaBufferID = buffers[priorityIndexInBuf];
441 while(priorityIndexInBuf < (numBuffers - 1) )
442 {
443 buffers[priorityIndexInBuf] = buffers[priorityIndexInBuf+1];
444 priorityIndexInBuf++;
445 }
446 buffers[numBuffers -1] = vaBufferID;
447 }
448 }
449
450