1 // Copyright (c) 2017-2019 Intel Corporation
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20
21 #include <mfxvideo.h>
22
23 #include <mfx_session.h>
24 #include <mfx_tools.h>
25 #include <mfx_common.h>
26 #include <mfx_user_plugin.h>
27
28 // sheduling and threading stuff
29 #include <mfx_task.h>
30
31 #ifdef MFX_ENABLE_VPP
32 // VPP include files here
33 #include "mfx_vpp_main.h" // this VideoVPP class builds VPP pipeline and run the VPP pipeline
34 #endif
35
36 template<>
Create(mfxVideoParam &)37 VideoVPP* _mfxSession::Create<VideoVPP>(mfxVideoParam& /*par*/)
38 {
39 VideoVPP *pVPP = nullptr;
40
41 #ifdef MFX_ENABLE_VPP
42 VideoCORE* core = m_pCORE.get();
43 mfxStatus mfxRes = MFX_ERR_MEMORY_ALLOC;
44
45 pVPP = new VideoVPPMain(core, &mfxRes);
46 if (MFX_ERR_NONE != mfxRes)
47 {
48 delete pVPP;
49 pVPP = nullptr;
50 }
51 #endif // MFX_ENABLE_VPP
52
53 return pVPP;
54 }
55
MFXVideoVPP_Query(mfxSession session,mfxVideoParam * in,mfxVideoParam * out)56 mfxStatus MFXVideoVPP_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out)
57 {
58 MFX_AUTO_LTRACE_FUNC(MFX_TRACE_LEVEL_API);
59 MFX_LTRACE_BUFFER(MFX_TRACE_LEVEL_PARAMS, in);
60
61 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
62 MFX_CHECK(out, MFX_ERR_NULL_PTR);
63
64 if ((0 != in) && (MFX_HW_VAAPI == session->m_pCORE->GetVAType()))
65 {
66 // protected content not supported on Linux
67 if(0 != in->Protected)
68 {
69 out->Protected = 0;
70 return MFX_ERR_UNSUPPORTED;
71 }
72 }
73
74 mfxStatus mfxRes = MFX_ERR_UNSUPPORTED;
75 try
76 {
77 #ifdef MFX_ENABLE_USER_VPP
78 if (session->m_plgVPP.get())
79 {
80 mfxRes = session->m_plgVPP->Query(session->m_pCORE.get(), in, out);
81 }
82 else
83 {
84 #endif
85
86 #ifdef MFX_ENABLE_VPP
87 mfxRes = VideoVPPMain::Query(session->m_pCORE.get(), in, out);
88 #endif // MFX_ENABLE_VPP
89
90 #ifdef MFX_ENABLE_USER_VPP
91 }
92 #endif
93 }
94 // handle error(s)
95 catch(...)
96 {
97 mfxRes = MFX_ERR_NULL_PTR;
98 }
99
100 MFX_LTRACE_BUFFER(MFX_TRACE_LEVEL_PARAMS, out);
101 MFX_LTRACE_I(MFX_TRACE_LEVEL_PARAMS, mfxRes);
102 return mfxRes;
103 }
104
MFXVideoVPP_QueryIOSurf(mfxSession session,mfxVideoParam * par,mfxFrameAllocRequest * request)105 mfxStatus MFXVideoVPP_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request)
106 {
107 MFX_AUTO_LTRACE_FUNC(MFX_TRACE_LEVEL_API);
108 MFX_LTRACE_BUFFER(MFX_TRACE_LEVEL_PARAMS, par);
109
110 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
111 MFX_CHECK(par, MFX_ERR_NULL_PTR);
112 MFX_CHECK(request, MFX_ERR_NULL_PTR);
113
114 mfxStatus mfxRes = MFX_ERR_UNSUPPORTED;
115 try
116 {
117 #ifdef MFX_ENABLE_USER_VPP
118 if (session->m_plgVPP.get())
119 {
120 mfxRes = session->m_plgVPP->QueryIOSurf(session->m_pCORE.get(), par, &(request[0]), &(request[1]) );
121 }
122 else
123 {
124 #endif
125
126 #ifdef MFX_ENABLE_VPP
127 mfxRes = VideoVPPMain::QueryIOSurf(session->m_pCORE.get(), par, request/*, session->m_adapterNum*/);
128 #endif // MFX_ENABLE_VPP
129
130 #ifdef MFX_ENABLE_USER_VPP
131 }
132 #endif
133 }
134 // handle error(s)
135 catch(...)
136 {
137 mfxRes = MFX_ERR_NULL_PTR;
138 }
139
140 MFX_LTRACE_BUFFER(MFX_TRACE_LEVEL_PARAMS, request);
141 MFX_LTRACE_I(MFX_TRACE_LEVEL_PARAMS, mfxRes);
142 return mfxRes;
143 }
144
MFXVideoVPP_Init(mfxSession session,mfxVideoParam * par)145 mfxStatus MFXVideoVPP_Init(mfxSession session, mfxVideoParam *par)
146 {
147 mfxStatus mfxRes = MFX_ERR_UNSUPPORTED;
148
149 MFX_AUTO_LTRACE_FUNC(MFX_TRACE_LEVEL_API);
150 MFX_LTRACE_BUFFER(MFX_TRACE_LEVEL_PARAMS, par);
151
152 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
153 MFX_CHECK(par, MFX_ERR_NULL_PTR);
154
155 try
156 {
157 // check existence of component
158 if (!session->m_pVPP)
159 {
160 // create a new instance
161 session->m_pVPP.reset(session->Create<VideoVPP>(*par));
162 #ifdef MFX_ENABLE_VPP
163 MFX_CHECK(session->m_pVPP.get(), MFX_ERR_INVALID_VIDEO_PARAM);
164 #else
165 MFX_CHECK(session->m_pVPP.get(), MFX_ERR_UNSUPPORTED);
166 #endif
167 }
168
169 // create a new instance
170 mfxRes = session->m_pVPP->Init(par);
171 }
172 // handle error(s)
173 catch(...)
174 {
175 // set the default error value
176 mfxRes = MFX_ERR_UNKNOWN;
177 }
178
179 MFX_LTRACE_I(MFX_TRACE_LEVEL_PARAMS, mfxRes);
180 return mfxRes;
181 }
182
MFXVideoVPP_Close(mfxSession session)183 mfxStatus MFXVideoVPP_Close(mfxSession session)
184 {
185 mfxStatus mfxRes;
186
187 MFX_AUTO_LTRACE_FUNC(MFX_TRACE_LEVEL_API);
188
189 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
190 MFX_CHECK(session->m_pScheduler, MFX_ERR_NOT_INITIALIZED);
191
192 try
193 {
194 if (!session->m_pVPP)
195 {
196 return MFX_ERR_NOT_INITIALIZED;
197 }
198
199 // wait until all tasks are processed
200 session->m_pScheduler->WaitForAllTasksCompletion(session->m_pVPP.get());
201
202 mfxRes = session->m_pVPP->Close();
203 // delete the codec's instance if not plugin
204 if (!session->m_plgVPP)
205 {
206 session->m_pVPP.reset(nullptr);
207 }
208 }
209 // handle error(s)
210 catch(...)
211 {
212 // set the default error value
213 mfxRes = MFX_ERR_UNKNOWN;
214 }
215
216 MFX_LTRACE_I(MFX_TRACE_LEVEL_PARAMS, mfxRes);
217 return mfxRes;
218 }
219
220 static
MFXVideoVPPLegacyRoutine(void * pState,void * pParam,mfxU32 threadNumber,mfxU32)221 mfxStatus MFXVideoVPPLegacyRoutine(void *pState, void *pParam,
222 mfxU32 threadNumber, mfxU32 /* callNumber */)
223 {
224 MFX_AUTO_LTRACE_FUNC(MFX_TRACE_LEVEL_API);
225 VideoVPP *pVPP = (VideoVPP *) pState;
226 MFX_THREAD_TASK_PARAMETERS *pTaskParam = (MFX_THREAD_TASK_PARAMETERS *) pParam;
227 mfxStatus mfxRes;
228
229 // check error(s)
230 if ((NULL == pState) ||
231 (NULL == pParam) ||
232 (0 != threadNumber))
233 {
234 return MFX_ERR_NULL_PTR;
235 }
236
237 // call the obsolete method
238 mfxRes = pVPP->RunFrameVPP(pTaskParam->vpp.in,
239 pTaskParam->vpp.out,
240 pTaskParam->vpp.aux);
241
242 return mfxRes;
243
244 } // mfxStatus MFXVideoVPPLegacyRoutine(void *pState, void *pParam,
245
246 enum
247 {
248 MFX_NUM_ENTRY_POINTS = 2
249 };
250
MFXVideoVPP_RunFrameVPPAsync(mfxSession session,mfxFrameSurface1 * in,mfxFrameSurface1 * out,mfxExtVppAuxData * aux,mfxSyncPoint * syncp)251 mfxStatus MFXVideoVPP_RunFrameVPPAsync(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 *out, mfxExtVppAuxData *aux, mfxSyncPoint *syncp)
252 {
253 mfxStatus mfxRes;
254
255 MFX_AUTO_LTRACE_WITHID(MFX_TRACE_LEVEL_API, "MFX_RunFrameVPPAsync");
256 MFX_LTRACE_BUFFER(MFX_TRACE_LEVEL_PARAMS, aux);
257 MFX_LTRACE_BUFFER(MFX_TRACE_LEVEL_PARAMS, in);
258
259 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
260 MFX_CHECK(session->m_pVPP.get(), MFX_ERR_NOT_INITIALIZED);
261 MFX_CHECK(syncp, MFX_ERR_NULL_PTR);
262
263 try
264 {
265 #ifdef MFX_ENABLE_USER_VPP
266 if (session->m_plgVPP.get())
267 {
268 MFX_TASK task;
269 mfxSyncPoint syncPoint = NULL;
270 *syncp = NULL;
271 memset(&task, 0, sizeof(MFX_TASK));
272
273 mfxRes = session->m_plgVPP->VPPFrameCheck(in, out, aux, &task.entryPoint);
274
275 if (task.entryPoint.pRoutine)
276 {
277 mfxStatus mfxAddRes;
278
279 task.pOwner = session->m_plgVPP.get();
280 task.priority = session->m_priority;
281 task.threadingPolicy = session->m_plgVPP->GetThreadingPolicy();
282 // fill dependencies
283 task.pSrc[0] = in;
284 task.pDst[0] = out;
285 if (MFX_ERR_MORE_DATA_SUBMIT_TASK == static_cast<int>(mfxRes))
286 task.pDst[0] = NULL;
287
288 #ifdef MFX_TRACE_ENABLE
289 task.nParentId = MFX_AUTO_TRACE_GETID();
290 task.nTaskId = MFX::CreateUniqId() + MFX_TRACE_ID_VPP;
291 #endif
292
293 // register input and call the task
294 mfxAddRes = session->m_pScheduler->AddTask(task, &syncPoint);
295 if (MFX_ERR_NONE != mfxAddRes)
296 {
297 return mfxAddRes;
298 }
299 *syncp = syncPoint;
300 }
301 }
302 else
303 {
304 #endif
305 mfxSyncPoint syncPoint = NULL;
306 MFX_ENTRY_POINT entryPoints[MFX_NUM_ENTRY_POINTS];
307 mfxU32 numEntryPoints = MFX_NUM_ENTRY_POINTS;
308
309 memset(&entryPoints, 0, sizeof(entryPoints));
310 mfxRes = session->m_pVPP->VppFrameCheck(in, out, aux, entryPoints, numEntryPoints);
311 // source data is OK, go forward
312 if ((MFX_ERR_NONE == mfxRes) ||
313 (MFX_ERR_MORE_DATA_SUBMIT_TASK == static_cast<int>(mfxRes)) ||
314 (MFX_ERR_MORE_SURFACE == mfxRes) ||
315 (MFX_WRN_INCOMPATIBLE_VIDEO_PARAM == mfxRes))
316 {
317 // prepare the absolete kind of task.
318 // it is absolete and must be removed.
319 if (NULL == entryPoints[0].pRoutine)
320 {
321 MFX_TASK task;
322
323 memset(&task, 0, sizeof(task));
324 // BEGIN OF OBSOLETE PART
325 task.bObsoleteTask = true;
326 // fill task info
327 task.pOwner = session->m_pVPP.get();
328 task.entryPoint.pRoutine = &MFXVideoVPPLegacyRoutine;
329 task.entryPoint.pState = session->m_pVPP.get();
330 task.entryPoint.requiredNumThreads = 1;
331
332 // fill legacy parameters
333 task.obsolete_params.vpp.in = in;
334 task.obsolete_params.vpp.out = out;
335 task.obsolete_params.vpp.aux = aux;
336 // END OF OBSOLETE PART
337
338 task.priority = session->m_priority;
339 task.threadingPolicy = session->m_pVPP->GetThreadingPolicy();
340 // fill dependencies
341 task.pSrc[0] = in;
342 task.pDst[0] = out;
343
344 if (MFX_ERR_MORE_DATA_SUBMIT_TASK == static_cast<int>(mfxRes))
345 task.pDst[0] = NULL;
346
347 #ifdef MFX_TRACE_ENABLE
348 task.nParentId = MFX_AUTO_TRACE_GETID();
349 task.nTaskId = MFX::CreateUniqId() + MFX_TRACE_ID_VPP;
350 #endif // MFX_TRACE_ENABLE
351
352 // register input and call the task
353 MFX_CHECK_STS(session->m_pScheduler->AddTask(task, &syncPoint));
354 }
355 else if (1 == numEntryPoints)
356 {
357 MFX_TASK task;
358
359 memset(&task, 0, sizeof(task));
360 task.pOwner = session->m_pVPP.get();
361 task.entryPoint = entryPoints[0];
362 task.priority = session->m_priority;
363 task.threadingPolicy = session->m_pVPP->GetThreadingPolicy();
364 // fill dependencies
365 task.pSrc[0] = in;
366 task.pDst[0] = out;
367 if (MFX_ERR_MORE_DATA_SUBMIT_TASK == static_cast<int>(mfxRes))
368 task.pDst[0] = NULL;
369
370
371 #ifdef MFX_TRACE_ENABLE
372 task.nParentId = MFX_AUTO_TRACE_GETID();
373 task.nTaskId = MFX::CreateUniqId() + MFX_TRACE_ID_VPP;
374 #endif
375 // register input and call the task
376 MFX_CHECK_STS(session->m_pScheduler->AddTask(task, &syncPoint));
377 }
378 else
379 {
380 MFX_TASK task;
381
382 memset(&task, 0, sizeof(task));
383 task.pOwner = session->m_pVPP.get();
384 task.entryPoint = entryPoints[0];
385 task.priority = session->m_priority;
386 task.threadingPolicy = session->m_pVPP->GetThreadingPolicy();
387 // fill dependencies
388 task.pSrc[0] = in;
389 task.pDst[0] = entryPoints[0].pParam;
390
391
392 #ifdef MFX_TRACE_ENABLE
393 task.nParentId = MFX_AUTO_TRACE_GETID();
394 task.nTaskId = MFX::CreateUniqId() + MFX_TRACE_ID_VPP;
395 #endif
396 // register input and call the task
397 MFX_CHECK_STS(session->m_pScheduler->AddTask(task, &syncPoint));
398
399 memset(&task, 0, sizeof(task));
400 task.pOwner = session->m_pVPP.get();
401 task.entryPoint = entryPoints[1];
402 task.priority = session->m_priority;
403 task.threadingPolicy = session->m_pVPP->GetThreadingPolicy();
404
405 // fill dependencies
406 task.pSrc[0] = entryPoints[0].pParam;
407 task.pDst[0] = out;
408 task.pDst[1] = aux;
409 if (MFX_ERR_MORE_DATA_SUBMIT_TASK == static_cast<int>(mfxRes))
410 {
411 task.pDst[0] = NULL;
412 task.pDst[1] = NULL;
413 }
414
415 #ifdef MFX_TRACE_ENABLE
416 task.nParentId = MFX_AUTO_TRACE_GETID();
417 task.nTaskId = MFX::CreateUniqId() + MFX_TRACE_ID_VPP2;
418 #endif
419 // register input and call the task
420 MFX_CHECK_STS(session->m_pScheduler->AddTask(task, &syncPoint));
421 }
422
423 if (MFX_ERR_MORE_DATA_SUBMIT_TASK == static_cast<int>(mfxRes))
424 {
425 mfxRes = MFX_ERR_MORE_DATA;
426 syncPoint = NULL;
427 }
428 }
429
430 // return pointer to synchronization point
431 *syncp = syncPoint;
432 #ifdef MFX_ENABLE_USER_VPP
433 }
434 #endif
435 }
436 // handle error(s)
437 catch(...)
438 {
439 // set the default error value
440 mfxRes = MFX_ERR_UNKNOWN;
441 }
442
443 MFX_LTRACE_BUFFER(MFX_TRACE_LEVEL_PARAMS, out);
444 if (mfxRes == MFX_ERR_NONE && syncp)
445 {
446 MFX_LTRACE_P(MFX_TRACE_LEVEL_PARAMS, *syncp);
447 }
448 MFX_LTRACE_I(MFX_TRACE_LEVEL_PARAMS, mfxRes);
449 return mfxRes;
450
451 } // mfxStatus MFXVideoVPP_RunFrameVPPAsync(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 *out, mfxExtVppAuxData *aux, mfxSyncPoint *syncp)
452
MFXVideoVPP_RunFrameVPPAsyncEx(mfxSession session,mfxFrameSurface1 * in,mfxFrameSurface1 * surface_work,mfxFrameSurface1 ** surface_out,mfxSyncPoint * syncp)453 mfxStatus MFXVideoVPP_RunFrameVPPAsyncEx(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxSyncPoint *syncp)
454 {
455 #if !defined(MFX_ENABLE_USER_VPP)
456 (void)in;
457 (void)surface_work;
458 (void)surface_out;
459 #endif
460
461 mfxStatus mfxRes;
462
463 MFX_AUTO_LTRACE_WITHID(MFX_TRACE_LEVEL_API, "MFX_RunFrameVPPAsyncEx");
464 MFX_LTRACE_BUFFER(MFX_TRACE_LEVEL_PARAMS, in);
465
466 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
467 MFX_CHECK(session->m_pVPP.get(), MFX_ERR_NOT_INITIALIZED);
468 MFX_CHECK(syncp, MFX_ERR_NULL_PTR);
469
470 try
471 {
472 #ifdef MFX_ENABLE_USER_VPP
473 if (session->m_plgVPP.get())
474 {
475 MFX_TASK task;
476 mfxSyncPoint syncPoint = NULL;
477 *syncp = NULL;
478 memset(&task, 0, sizeof(MFX_TASK));
479
480 mfxRes = session->m_plgVPP->VPPFrameCheckEx(in, surface_work, surface_out, &task.entryPoint);
481
482 if (task.entryPoint.pRoutine)
483 {
484 mfxStatus mfxAddRes;
485
486 task.pOwner = session->m_plgVPP.get();
487 task.priority = session->m_priority;
488 task.threadingPolicy = session->m_plgVPP->GetThreadingPolicy();
489 // fill dependencies
490 task.pSrc[0] = in;
491 task.pDst[0] = surface_work;
492 if (MFX_ERR_MORE_DATA_SUBMIT_TASK == static_cast<int>(mfxRes))
493 task.pDst[0] = NULL;
494
495 #ifdef MFX_TRACE_ENABLE
496 task.nParentId = MFX_AUTO_TRACE_GETID();
497 task.nTaskId = MFX::CreateUniqId() + MFX_TRACE_ID_VPP;
498 #endif
499
500 // register input and call the task
501 mfxAddRes = session->m_pScheduler->AddTask(task, &syncPoint);
502 if (MFX_ERR_NONE != mfxAddRes)
503 {
504 return mfxAddRes;
505 }
506 *syncp = syncPoint;
507 }
508 }
509 else
510 {
511 #endif
512 //MediaSDK's VPP should not work through Ex function
513 return MFX_ERR_UNDEFINED_BEHAVIOR;
514
515 #ifdef MFX_ENABLE_USER_VPP
516 }
517 #endif
518 }
519 // handle error(s)
520 catch(...)
521 {
522 // set the default error value
523 mfxRes = MFX_ERR_UNKNOWN;
524 }
525
526 MFX_LTRACE_BUFFER(MFX_TRACE_LEVEL_PARAMS, surface_work);
527 if (mfxRes == MFX_ERR_NONE && syncp)
528 {
529 MFX_LTRACE_P(MFX_TRACE_LEVEL_PARAMS, *syncp);
530 }
531 MFX_LTRACE_I(MFX_TRACE_LEVEL_PARAMS, mfxRes);
532 return mfxRes;
533
534 } // mfxStatus MFXVideoVPP_RunFrameVPPAsyncEx(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxThreadTask *task);
535
536 //
537 // THE OTHER VPP FUNCTIONS HAVE IMPLICIT IMPLEMENTATION
538 //
539
540 FUNCTION_RESET_IMPL(VPP, Reset, (mfxSession session, mfxVideoParam *par), (par))
541
542 FUNCTION_IMPL(VPP, GetVideoParam, (mfxSession session, mfxVideoParam *par), (par))
543 FUNCTION_IMPL(VPP, GetVPPStat, (mfxSession session, mfxVPPStat *stat), (stat))
544