1 // Copyright (c) 2017-2020 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 "mfx_common.h"
22
23 #if defined (MFX_ENABLE_VPP)
24 #if defined (MFX_VA_LINUX)
25
26 #include "mfx_session.h"
27 #include <math.h>
28 #include "mfx_vpp_defs.h"
29 #include "mfx_vpp_vaapi.h"
30 #include "mfx_utils.h"
31 #include "libmfx_core_vaapi.h"
32 #include <algorithm>
33
34 template<typename T>
SetPlaneROI(T value,T * pDst,int dstStep,mfxSize roiSize)35 bool SetPlaneROI(T value, T* pDst, int dstStep, mfxSize roiSize)
36 {
37 if (!pDst || roiSize.width < 0 || roiSize.height < 0)
38 return false;
39
40 for(int h = 0; h < roiSize.height; h++ ) {
41 std::fill(pDst, pDst + roiSize.width, value);
42 pDst = (T *)((unsigned char*)pDst + dstStep);
43 }
44
45 return true;
46 }
47
48
49 enum QueryStatus
50 {
51 VPREP_GPU_READY = 0,
52 VPREP_GPU_BUSY = 1,
53 VPREP_GPU_NOT_REACHED = 2,
54 VPREP_GPU_FAILED = 3
55 };
56
57 //////////////////////////////////////////////////////////////////////////
58 using namespace MfxHwVideoProcessing;
59
convertValue(const float OldMin,const float OldMax,const float NewMin,const float NewMax,const float OldValue)60 static float convertValue(const float OldMin,const float OldMax,const float NewMin,const float NewMax,const float OldValue)
61 {
62 if((0 == NewMin) && (0 == NewMax)) return OldValue; //workaround
63 float oldRange = OldMax - OldMin;
64 float newRange = NewMax - NewMin;
65 return (((OldValue - OldMin) * newRange) / oldRange) + NewMin;
66 }
67
68 #define DEFAULT_HUE 0
69 #define DEFAULT_SATURATION 1
70 #define DEFAULT_CONTRAST 1
71 #define DEFAULT_BRIGHTNESS 0
72
73
74 #define VA_TOP_FIELD_WEAVE 0x00000004
75 #define VA_BOTTOM_FIELD_WEAVE 0x00000008
76
77 #define VPP_COMP_BACKGROUND_SURFACE_WIDTH 320
78 #define VPP_COMP_BACKGROUND_SURFACE_HEIGHT 256
79
VAAPIVideoProcessing()80 VAAPIVideoProcessing::VAAPIVideoProcessing():
81 m_bRunning(false)
82 , m_core(NULL)
83 , m_vaDisplay(0)
84 , m_vaConfig(VA_INVALID_ID)
85 , m_vaContextVPP(VA_INVALID_ID)
86 , m_denoiseFilterID(VA_INVALID_ID)
87 , m_detailFilterID(VA_INVALID_ID)
88 , m_deintFilterID(VA_INVALID_ID)
89 , m_procampFilterID(VA_INVALID_ID)
90 , m_frcFilterID(VA_INVALID_ID)
91 , m_gpuPriorityID(VA_INVALID_ID)
92 , m_deintFrameCount(0)
93 #ifdef MFX_ENABLE_VPP_FRC
94 , m_frcCyclicCounter(0)
95 #endif
96 , m_numFilterBufs(0)
97 , m_MaxContextPriority(0)
98 , m_primarySurface4Composition(NULL)
99 {
100
101 for(int i = 0; i < VAProcFilterCount; i++)
102 m_filterBufs[i] = VA_INVALID_ID;
103
104 memset( (void*)&m_pipelineCaps, 0, sizeof(m_pipelineCaps));
105 memset( (void*)&m_denoiseCaps, 0, sizeof(m_denoiseCaps));
106 memset( (void*)&m_detailCaps, 0, sizeof(m_detailCaps));
107 memset( (void*)&m_deinterlacingCaps, 0, sizeof(m_deinterlacingCaps));
108 #ifdef MFX_ENABLE_VPP_FRC
109 memset( (void*)&m_frcCaps, 0, sizeof(m_frcCaps));
110 #endif
111 memset( (void*)&m_procampCaps, 0, sizeof(m_procampCaps));
112
113 m_cachedReadyTaskIndex.clear();
114 m_feedbackCache.clear();
115
116 } // VAAPIVideoProcessing::VAAPIVideoProcessing()
117
118
~VAAPIVideoProcessing()119 VAAPIVideoProcessing::~VAAPIVideoProcessing()
120 {
121 Close();
122
123 } // VAAPIVideoProcessing::~VAAPIVideoProcessing()
124
CreateDevice(VideoCORE * core,mfxVideoParam * pParams,bool)125 mfxStatus VAAPIVideoProcessing::CreateDevice(VideoCORE * core, mfxVideoParam* pParams, bool /*isTemporal*/)
126 {
127 MFX_CHECK_NULL_PTR1( core );
128
129 VAAPIVideoCORE* hwCore = dynamic_cast<VAAPIVideoCORE*>(core);
130
131 MFX_CHECK_NULL_PTR1( hwCore );
132
133 mfxStatus sts = hwCore->GetVAService( &m_vaDisplay);
134 MFX_CHECK_STS( sts );
135
136 sts = Init( &m_vaDisplay, pParams);
137
138 MFX_CHECK_STS(sts);
139
140 m_cachedReadyTaskIndex.clear();
141
142 m_core = core;
143
144 return MFX_ERR_NONE;
145
146 } // mfxStatus VAAPIVideoProcessing::CreateDevice(VideoCORE * core, mfxInitParams* pParams)
147
148
DestroyDevice(void)149 mfxStatus VAAPIVideoProcessing::DestroyDevice(void)
150 {
151 mfxStatus sts = Close();
152
153 return sts;
154
155 } // mfxStatus VAAPIVideoProcessing::DestroyDevice(void)
156
157
Close(void)158 mfxStatus VAAPIVideoProcessing::Close(void)
159 {
160 VAStatus vaSts;
161 if (m_primarySurface4Composition != NULL)
162 {
163 vaSts = vaDestroySurfaces(m_vaDisplay,m_primarySurface4Composition,1);
164 std::ignore = MFX_STS_TRACE(vaSts);
165
166 free(m_primarySurface4Composition);
167 m_primarySurface4Composition = NULL;
168 }
169
170 mfxStatus sts = CheckAndDestroyVAbuffer(m_vaDisplay, m_denoiseFilterID);
171 std::ignore = MFX_STS_TRACE(sts);
172
173 sts = CheckAndDestroyVAbuffer(m_vaDisplay, m_detailFilterID);
174 std::ignore = MFX_STS_TRACE(sts);
175
176 sts = CheckAndDestroyVAbuffer(m_vaDisplay, m_procampFilterID);
177 std::ignore = MFX_STS_TRACE(sts);
178
179 sts = CheckAndDestroyVAbuffer(m_vaDisplay, m_deintFilterID);
180 std::ignore = MFX_STS_TRACE(sts);
181
182 sts = CheckAndDestroyVAbuffer(m_vaDisplay, m_frcFilterID);
183 std::ignore = MFX_STS_TRACE(sts);
184
185 if (m_vaContextVPP != VA_INVALID_ID)
186 {
187 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaDestroyContext");
188 vaSts = vaDestroyContext( m_vaDisplay, m_vaContextVPP );
189 std::ignore = MFX_STS_TRACE(vaSts);
190
191 m_vaContextVPP = VA_INVALID_ID;
192 }
193
194 if (m_vaConfig != VA_INVALID_ID)
195 {
196 vaSts = vaDestroyConfig( m_vaDisplay, m_vaConfig );
197 std::ignore = MFX_STS_TRACE(vaSts);
198
199 m_vaConfig = VA_INVALID_ID;
200 }
201
202 for(int i = 0; i < VAProcFilterCount; i++)
203 m_filterBufs[i] = VA_INVALID_ID;
204
205 m_denoiseFilterID = VA_INVALID_ID;
206 m_deintFilterID = VA_INVALID_ID;
207 m_procampFilterID = VA_INVALID_ID;
208
209 memset( (void*)&m_pipelineCaps, 0, sizeof(m_pipelineCaps));
210 memset( (void*)&m_denoiseCaps, 0, sizeof(m_denoiseCaps));
211 memset( (void*)&m_detailCaps, 0, sizeof(m_detailCaps));
212 memset( (void*)&m_procampCaps, 0, sizeof(m_procampCaps));
213 memset( (void*)&m_deinterlacingCaps, 0, sizeof(m_deinterlacingCaps));
214
215 return MFX_ERR_NONE;
216
217 } // mfxStatus VAAPIVideoProcessing::Close(void)
218
Init(_mfxPlatformAccelerationService * pVADisplay,mfxVideoParam * pParams)219 mfxStatus VAAPIVideoProcessing::Init(_mfxPlatformAccelerationService* pVADisplay, mfxVideoParam* pParams)
220 {
221 if(false == m_bRunning)
222 {
223 MFX_CHECK_NULL_PTR1( pVADisplay );
224 MFX_CHECK_NULL_PTR1( pParams );
225
226 m_cachedReadyTaskIndex.clear();
227
228 VAEntrypoint* va_entrypoints = NULL;
229 VAStatus vaSts;
230 int va_max_num_entrypoints = vaMaxNumEntrypoints(m_vaDisplay);
231 if(va_max_num_entrypoints)
232 va_entrypoints = new VAEntrypoint[va_max_num_entrypoints];
233 else
234 return MFX_ERR_DEVICE_FAILED;
235
236 mfxI32 entrypointsCount = 0, entrypointsIndx = 0;
237
238 vaSts = vaQueryConfigEntrypoints(m_vaDisplay,
239 VAProfileNone,
240 va_entrypoints,
241 &entrypointsCount);
242 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
243
244 for( entrypointsIndx = 0; entrypointsIndx < entrypointsCount; entrypointsIndx++ )
245 {
246 if( VAEntrypointVideoProc == va_entrypoints[entrypointsIndx] )
247 {
248 m_bRunning = true;
249 break;
250 }
251 }
252 delete[] va_entrypoints;
253
254 if( !m_bRunning )
255 {
256 return MFX_ERR_DEVICE_FAILED;
257 }
258
259 vaSts = vaCreateConfig( m_vaDisplay,
260 VAProfileNone,
261 VAEntrypointVideoProc,
262 NULL,
263 0,
264 &m_vaConfig);
265 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
266
267 // Context
268 int width = pParams->vpp.Out.Width;
269 int height = pParams->vpp.Out.Height;
270
271 {
272 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaCreateContext");
273 vaSts = vaCreateContext(m_vaDisplay,
274 m_vaConfig,
275 width,
276 height,
277 VA_PROGRESSIVE,
278 0, 0,
279 &m_vaContextVPP);
280 }
281 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
282 }
283
284 return MFX_ERR_NONE;
285
286 } // mfxStatus VAAPIVideoProcessing::Init(_mfxPlatformAccelerationService* pVADisplay, mfxVideoParam* pParams)
287
288
Register(mfxHDLPair *,mfxU32,BOOL)289 mfxStatus VAAPIVideoProcessing::Register(
290 mfxHDLPair* /*pSurfaces*/,
291 mfxU32 /*num*/,
292 BOOL /*bRegister*/)
293 {
294 return MFX_ERR_NONE;
295 } // mfxStatus VAAPIVideoProcessing::Register(_mfxPlatformVideoSurface *pSurfaces, ...)
296
297
QueryCapabilities(mfxVppCaps & caps)298 mfxStatus VAAPIVideoProcessing::QueryCapabilities(mfxVppCaps& caps)
299 {
300 VAStatus vaSts;
301
302 VAProcFilterType filters[VAProcFilterCount];
303 mfxU32 num_filters = VAProcFilterCount;
304
305 vaSts = vaQueryVideoProcFilters(m_vaDisplay, m_vaContextVPP, filters, &num_filters);
306 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
307
308 mfxU32 num_procamp_caps = VAProcColorBalanceCount;
309 vaSts = vaQueryVideoProcFilterCaps(m_vaDisplay,
310 m_vaContextVPP,
311 VAProcFilterColorBalance,
312 &m_procampCaps, &num_procamp_caps);
313 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
314
315 mfxU32 num_denoise_caps = 1;
316 vaSts = vaQueryVideoProcFilterCaps(m_vaDisplay,
317 m_vaContextVPP,
318 VAProcFilterNoiseReduction,
319 &m_denoiseCaps, &num_denoise_caps);
320 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
321
322 mfxU32 num_detail_caps = 1;
323 vaSts = vaQueryVideoProcFilterCaps(m_vaDisplay,
324 m_vaContextVPP,
325 VAProcFilterSharpening,
326 &m_detailCaps, &num_detail_caps);
327 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
328
329 mfxU32 num_deinterlacing_caps = VAProcDeinterlacingCount;
330 vaSts = vaQueryVideoProcFilterCaps(m_vaDisplay,
331 m_vaContextVPP,
332 VAProcFilterDeinterlacing,
333 &m_deinterlacingCaps, &num_deinterlacing_caps);
334 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
335
336 #ifdef MFX_ENABLE_VPP_FRC
337 /* to check is FRC enabled or not*/
338 /* first need to get number of modes supported by driver*/
339 VAProcFilterCapFrameRateConversion tempFRC_Caps;
340 mfxU32 num_frc_caps = 1;
341
342 tempFRC_Caps.bget_custom_rates = 1;
343 vaSts = vaQueryVideoProcFilterCaps(m_vaDisplay,
344 m_vaContextVPP,
345 VAProcFilterFrameRateConversion,
346 &tempFRC_Caps, &num_frc_caps);
347 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
348
349 if (0 != tempFRC_Caps.frc_custom_rates) /* FRC is enabled, at least one mode */
350 {
351 caps.uFrameRateConversion = 1 ;
352 /* Again, only two modes: 24p->60p and 30p->60p is available
353 * But driver report 3, but 3rd is equal to 2rd,
354 * So only 2 real modes*/
355 if (tempFRC_Caps.frc_custom_rates > 2)
356 tempFRC_Caps.frc_custom_rates = 2;
357 caps.frcCaps.customRateData.resize(tempFRC_Caps.frc_custom_rates);
358 /*to get details about each mode */
359 tempFRC_Caps.bget_custom_rates = 0;
360
361 for (mfxU32 ii = 0; ii < tempFRC_Caps.frc_custom_rates; ii++)
362 {
363 m_frcCaps[ii].frc_custom_rates = ii + 1;
364 vaSts = vaQueryVideoProcFilterCaps(m_vaDisplay,
365 m_vaContextVPP,
366 VAProcFilterFrameRateConversion,
367 &m_frcCaps[ii], &num_frc_caps);
368 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
369 caps.frcCaps.customRateData[ii].inputFramesOrFieldPerCycle = m_frcCaps[ii].input_frames;
370 caps.frcCaps.customRateData[ii].outputIndexCountPerCycle = m_frcCaps[ii].output_frames;
371 /* out frame rate*/
372 caps.frcCaps.customRateData[ii].customRate.FrameRateExtN = m_frcCaps[ii].output_fps;
373 /*input frame rate */
374 caps.frcCaps.customRateData[ii].customRate.FrameRateExtD = m_frcCaps[ii].input_fps;
375 }
376 }
377 #endif // #ifdef MFX_ENABLE_VPP_FRC
378
379 for( mfxU32 filtersIndx = 0; filtersIndx < num_filters; filtersIndx++ )
380 {
381 if (filters[filtersIndx])
382 {
383 switch (filters[filtersIndx])
384 {
385 case VAProcFilterNoiseReduction:
386 caps.uDenoiseFilter = 1;
387 break;
388 case VAProcFilterSharpening:
389 caps.uDetailFilter = 1;
390 break;
391 case VAProcFilterDeinterlacing:
392 for (mfxU32 i = 0; i < num_deinterlacing_caps; i++)
393 {
394 if (VAProcDeinterlacingBob == m_deinterlacingCaps[i].type)
395 caps.uSimpleDI = 1;
396 if (VAProcDeinterlacingWeave == m_deinterlacingCaps[i].type ||
397 VAProcDeinterlacingMotionAdaptive == m_deinterlacingCaps[i].type ||
398 VAProcDeinterlacingMotionCompensated == m_deinterlacingCaps[i].type)
399 caps.uAdvancedDI = 1;
400 }
401 break;
402 case VAProcFilterColorBalance:
403 caps.uProcampFilter = 1;
404 break;
405 default:
406 break;
407 }
408 }
409 }
410
411 memset(&m_pipelineCaps, 0, sizeof(VAProcPipelineCaps));
412 vaSts = vaQueryVideoProcPipelineCaps(m_vaDisplay,
413 m_vaContextVPP,
414 NULL,
415 0,
416 &m_pipelineCaps);
417 #ifdef MFX_ENABLE_VPP_ROTATION
418 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
419 if (m_pipelineCaps.rotation_flags & (1 << VA_ROTATION_90 ) &&
420 m_pipelineCaps.rotation_flags & (1 << VA_ROTATION_180) &&
421 m_pipelineCaps.rotation_flags & (1 << VA_ROTATION_270))
422 {
423 caps.uRotation = 1;
424 }
425 #endif
426
427 if ((m_pipelineCaps.mirror_flags & VA_MIRROR_HORIZONTAL) &&
428 (m_pipelineCaps.mirror_flags & VA_MIRROR_VERTICAL))
429 {
430 caps.uMirroring = 1;
431 }
432
433 if (m_pipelineCaps.max_output_width && m_pipelineCaps.max_output_height)
434 {
435 caps.uMaxWidth = m_pipelineCaps.max_output_width;
436 caps.uMaxHeight = m_pipelineCaps.max_output_height;
437 }
438 else
439 {
440 caps.uMaxWidth = 4096;
441 caps.uMaxHeight = 4096;
442 }
443
444 caps.uFieldWeavingControl = 1;
445
446 // [FourCC]
447 // should be changed by libva support
448 for (auto fourcc : g_TABLE_SUPPORTED_FOURCC)
449 {
450 // Mark supported input
451 switch(fourcc)
452 {
453 case MFX_FOURCC_NV12:
454 case MFX_FOURCC_YV12:
455 case MFX_FOURCC_YUY2:
456 case MFX_FOURCC_UYVY:
457 case MFX_FOURCC_RGB4:
458 #if defined (MFX_ENABLE_FOURCC_RGB565)
459 case MFX_FOURCC_RGB565:
460 #endif
461 #ifdef MFX_ENABLE_RGBP
462 case MFX_FOURCC_RGBP:
463 #endif
464 #if (MFX_VERSION >= 1027)
465 case MFX_FOURCC_AYUV:
466 case MFX_FOURCC_Y210:
467 case MFX_FOURCC_Y410:
468 #endif
469 #if (MFX_VERSION >= 1031)
470 case MFX_FOURCC_P016:
471 case MFX_FOURCC_Y216:
472 case MFX_FOURCC_Y416:
473 #endif
474 case MFX_FOURCC_P010:
475 // A2RGB10 supported as input in case of passthru copy
476 case MFX_FOURCC_A2RGB10:
477 caps.mFormatSupport[fourcc] |= MFX_FORMAT_SUPPORT_INPUT;
478 break;
479 default:
480 break;
481 }
482
483 // Mark supported output
484 switch(fourcc)
485 {
486 case MFX_FOURCC_NV12:
487 case MFX_FOURCC_YV12:
488 case MFX_FOURCC_YUY2:
489 case MFX_FOURCC_RGB4:
490 case MFX_FOURCC_UYVY:
491 #if (MFX_VERSION >= 1027)
492 case MFX_FOURCC_AYUV:
493 case MFX_FOURCC_Y210:
494 case MFX_FOURCC_Y410:
495 #endif
496 #ifdef MFX_ENABLE_RGBP
497 case MFX_FOURCC_RGBP:
498 #endif
499 #if (MFX_VERSION >= 1031)
500 case MFX_FOURCC_P016:
501 case MFX_FOURCC_Y216:
502 case MFX_FOURCC_Y416:
503 #endif
504 case MFX_FOURCC_P010:
505 case MFX_FOURCC_A2RGB10:
506 caps.mFormatSupport[fourcc] |= MFX_FORMAT_SUPPORT_OUTPUT;
507 break;
508 default:
509 break;
510 }
511 }
512
513 caps.uScaling = 1;
514
515 eMFXPlatform platform = m_core->GetPlatformType();
516 if (platform == MFX_PLATFORM_HARDWARE)
517 {
518 caps.uChromaSiting = m_core->GetHWType() >= MFX_HW_SCL ? 1 : 0;
519 }
520
521 std::vector<VAConfigAttrib> attrib(1);
522 attrib[0].type = VAConfigAttribContextPriority;
523 vaSts = vaGetConfigAttributes(m_vaDisplay,
524 VAProfileNone,
525 VAEntrypointVideoProc,
526 attrib.data(),
527 attrib.size());
528 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
529 if (attrib[0].value != VA_ATTRIB_NOT_SUPPORTED)
530 m_MaxContextPriority = attrib[0].value;
531
532 return MFX_ERR_NONE;
533
534 } // mfxStatus VAAPIVideoProcessing::QueryCapabilities(mfxVppCaps& caps)
535
536 /// Setup VPP VAAPI driver parameters
537 /*!
538 Setup VPP surfaces and VPP VAAPI parameters.
539
540 \param[in] pParams
541 structure with VPP parameters and associated input and reference surfaces.
542 \param[out] deint
543 VAProcFilterParameterBufferDeinterlacing structure containing deinterlace information (scene change, which field to display).
544 \param[out] m_pipelineParam
545 VAProcPipelineParameterBuffer structure containing input and reference frames.
546
547 return mfxStatus
548 MFX_ERR_NONE id successful
549 */
Execute(mfxExecuteParams * pParams)550 mfxStatus VAAPIVideoProcessing::Execute(mfxExecuteParams *pParams)
551 {
552 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_HOTSPOTS, "VAAPIVideoProcessing::Execute");
553
554 bool bIsFirstField = true;
555 bool bUseReference = false;
556 VAStatus vaSts = VA_STATUS_SUCCESS;
557
558 VAAPIVideoCORE* hwCore = dynamic_cast<VAAPIVideoCORE*>(m_core);
559 eMFXHWType hwType = hwCore->GetHWType();
560
561 // NOTE the following variables should be visible till vaRenderPicture/vaEndPicture,
562 // not till vaCreateBuffer as the data they hold are passed to the driver via a pointer
563 // to the memory and driver simply copies the pointer till further dereference in the
564 // functions noted above. Thus, safer to simply make sure these variable are visible
565 // thru the whole scope of the function.
566 VARectangle input_region, output_region;
567
568 MFX_CHECK_NULL_PTR1( pParams );
569 MFX_CHECK_NULL_PTR1( pParams->targetSurface.hdl.first );
570 MFX_CHECK_NULL_PTR1( pParams->pRefSurfaces );
571 MFX_CHECK_NULL_PTR1( pParams->pRefSurfaces[0].hdl.first );
572
573 /* There is a special case for composition */
574 mfxStatus mfxSts = MFX_ERR_NONE;
575 if (pParams->bComposite)
576 {
577 if ((pParams->iTilesNum4Comp > 0) || (isVideoWall(pParams)) )
578 {
579 mfxSts = Execute_Composition_TiledVideoWall(pParams);
580 if (MFX_ERR_NONE == mfxSts)
581 return mfxSts;
582 }
583 /* if there is errors in params for tiling usage it may work for usual composition */
584 else
585 mfxSts = Execute_Composition(pParams);
586 return mfxSts;
587 }
588
589
590 // This works for ADI 30i->30p for now
591 // Better way may involve enabling bEOS for 30i->30p mode
592 if ((1 == pParams->refCount) && (pParams->bDeinterlace30i60p == false))
593 m_deintFrameCount = 0;
594
595 if (VA_INVALID_ID == m_deintFilterID)
596 {
597 if (pParams->iDeinterlacingAlgorithm)
598 {
599 VAProcFilterParameterBufferDeinterlacing deint;
600 deint.type = VAProcFilterDeinterlacing;
601 deint.flags = 0;
602
603 if (MFX_DEINTERLACING_BOB == pParams->iDeinterlacingAlgorithm)
604 {
605 deint.algorithm = VAProcDeinterlacingBob;
606 }
607 else if(0 == pParams->iDeinterlacingAlgorithm) // skip DI for progressive frames
608 {
609 deint.algorithm = VAProcDeinterlacingNone;
610 }
611 else
612 {
613 deint.algorithm = VAProcDeinterlacingMotionAdaptive;
614 }
615
616 // Get picture structure of ouput frame
617 mfxDrvSurface* pRefSurf_frameInfo = &(pParams->pRefSurfaces[0]); // previous input frame
618 mfxDrvSurface *pCurSurf_frameInfo = &(pParams->pRefSurfaces[pParams->bkwdRefCount]); // current input frame
619
620 // PicStruc can take values: MFX_PICSTRUCT_PROGRESSIVE | MFX_PICSTRUCT_FIELD_TFF | MFX_PICSTRUCT_FIELD_REPEATED=0x10
621 // default deint.flags = 0 is for top field in TFF frame.
622 if (pCurSurf_frameInfo->frameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE)
623 deint.flags = VA_DEINTERLACING_ONE_FIELD;
624 else if (pCurSurf_frameInfo->frameInfo.PicStruct & MFX_PICSTRUCT_FIELD_BFF)
625 deint.flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST | VA_DEINTERLACING_BOTTOM_FIELD;
626
627 /* Deinterlacer:
628 * BOB is used in first output frame (pParams->refCount = 1) and
629 * when scene change flag is set (pParams->scene > 0) ADI is
630 * used otherwise.
631 * ADI output is late by one field. Current and reference field
632 * are fed into de-interlacer.
633 **/
634
635 /* ADI 30i->30p: To get first field of current frame only
636 * For TFF cases, deint.flags required to set VA_DEINTERLACING_ONE_FIELD
637 * ensure driver go 30i->30p mode and surface set correct
638 * For BFF cases, deint.flags required to set all bits
639 * ensure driver go 30i->30p mode and surface set correct
640 **/
641 if(deint.algorithm == VAProcDeinterlacingMotionAdaptive && (pParams->refCount > 1))
642 {
643 if (MFX_PICSTRUCT_FIELD_TFF & pCurSurf_frameInfo->frameInfo.PicStruct)
644 deint.flags = VA_DEINTERLACING_ONE_FIELD;
645 else /* For BFF case required to set all bits */
646 deint.flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST | VA_DEINTERLACING_BOTTOM_FIELD | VA_DEINTERLACING_ONE_FIELD;
647 }
648
649 /* For 30i->60p case we have to indicate
650 * to driver which field Top or Bottom we a going to send.
651 * ADI uses reference frame and start after first frame:
652 * m_deintFrameCount==1, if TFF, TOP=second field of reference, BOTTOM=first field of current
653 * BOB, ADI_no_ref do not use reference frame and are used on first frame:
654 * m_deintFrameCount==0, if TFF, TOP=first field of current, BOTTOM=seconf field of current.
655 */
656 if (pParams->bDeinterlace30i60p == true)
657 {
658 mfxU32 refFramePicStruct = pRefSurf_frameInfo->frameInfo.PicStruct;
659 mfxU32 currFramePicStruct = pCurSurf_frameInfo->frameInfo.PicStruct;
660 bool isCurrentProgressive = false;
661 bool isPreviousProgressive = false;
662 bool isSameParity = false;
663
664 // Deinterlace with reference can be used after first frame is processed
665 if(pParams->refCount > 1 && m_deintFrameCount)
666 bUseReference = true;
667
668 // Check if previous is progressive
669 if ((refFramePicStruct == MFX_PICSTRUCT_PROGRESSIVE) ||
670 (refFramePicStruct & MFX_PICSTRUCT_FIELD_REPEATED) ||
671 (refFramePicStruct & MFX_PICSTRUCT_FRAME_DOUBLING) ||
672 (refFramePicStruct & MFX_PICSTRUCT_FRAME_TRIPLING))
673 {
674 isPreviousProgressive = true;
675 }
676
677 if ((currFramePicStruct == MFX_PICSTRUCT_PROGRESSIVE) ||
678 (currFramePicStruct & MFX_PICSTRUCT_FIELD_REPEATED) ||
679 (currFramePicStruct & MFX_PICSTRUCT_FRAME_DOUBLING) ||
680 (currFramePicStruct & MFX_PICSTRUCT_FRAME_TRIPLING))
681 {
682 isCurrentProgressive = true;
683 }
684
685 // Use BOB when scene change occur
686 if ( MFX_DEINTERLACING_ADVANCED_SCD == pParams->iDeinterlacingAlgorithm &&
687 ( pParams->scene != VPP_NO_SCENE_CHANGE))
688 bUseReference = false;
689
690 // Set up wich field to display for 30i->60p mode
691 // ADI uses second Field on even frames
692 // BOB, ADI_no_ref uses second Field on odd frames
693 if (0 == (m_deintFrameCount %2) && bUseReference)
694 {
695 bIsFirstField = false;
696 }
697 else if (1 == (m_deintFrameCount %2) && ((!bUseReference)))
698 {
699 bIsFirstField = false;
700 }
701
702 // Set deinterlace flag depending on parity and field to display
703 if (bIsFirstField) // output is second field of previous input
704 {
705 if (MFX_PICSTRUCT_FIELD_TFF & pRefSurf_frameInfo->frameInfo.PicStruct)
706 deint.flags = 0;
707 else
708 deint.flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST | VA_DEINTERLACING_BOTTOM_FIELD;
709 }
710 else // output is first field of current input
711 {
712 if (MFX_PICSTRUCT_FIELD_TFF & pCurSurf_frameInfo->frameInfo.PicStruct)
713 deint.flags = VA_DEINTERLACING_BOTTOM_FIELD;
714 else
715 deint.flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
716 }
717
718 // case where previous and current have different parity -> use ADI no ref on current
719 // To avoid frame duplication
720
721 if((refFramePicStruct & MFX_PICSTRUCT_FIELD_TFF) && (currFramePicStruct & MFX_PICSTRUCT_FIELD_TFF))
722 isSameParity = true;
723 else if((refFramePicStruct & MFX_PICSTRUCT_FIELD_BFF) && (currFramePicStruct & MFX_PICSTRUCT_FIELD_BFF))
724 isSameParity = true;
725
726 if((!isPreviousProgressive) && (!isCurrentProgressive) && (!isSameParity))
727 {
728 // Current is BFF
729 if(!bIsFirstField && (currFramePicStruct & MFX_PICSTRUCT_FIELD_BFF))
730 {
731 deint.flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST | VA_DEINTERLACING_BOTTOM_FIELD;
732 pParams->refCount =1; // Force ADI no ref on first Field of current frame
733 }
734
735 // Current is TFF
736 if(!bIsFirstField && (currFramePicStruct & MFX_PICSTRUCT_FIELD_TFF))
737 {
738 deint.flags = 0;
739 pParams->refCount =1; // Force ADI no ref on first Field of current frame
740 }
741 }
742 } // if ((30i->60p) && (pParams->refCount > 1)) /* 30i->60p mode only*/
743
744 /* Process special case and scene change flag*/
745 if ( MFX_DEINTERLACING_ADVANCED_SCD == pParams->iDeinterlacingAlgorithm &&
746 ( pParams->scene != VPP_NO_SCENE_CHANGE))
747 {
748 if(pParams->bDeinterlace30i60p) // 30i->60p mode
749 {
750 // In case of multiple scene changes, use BOB with same field to avoid out of frame order
751 if(VPP_MORE_SCENE_CHANGE_DETECTED == pParams->scene)
752 {
753 if (MFX_PICSTRUCT_FIELD_TFF & pCurSurf_frameInfo->frameInfo.PicStruct)
754 deint.flags = 0;
755 else /* BFF */
756 deint.flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST | VA_DEINTERLACING_BOTTOM_FIELD;
757 }
758 }
759 else /* BOB 30i->30p use First Field to generate output*/
760 {
761 if (MFX_PICSTRUCT_FIELD_TFF & pCurSurf_frameInfo->frameInfo.PicStruct)
762 deint.flags = 0;
763 else /* Frame is BFF */
764 deint.flags = VA_DEINTERLACING_BOTTOM_FIELD_FIRST | VA_DEINTERLACING_BOTTOM_FIELD;
765 }
766
767 deint.flags |= VA_DEINTERLACING_SCD_ENABLE; // It forces BOB
768 }
769
770 vaSts = vaCreateBuffer(m_vaDisplay,
771 m_vaContextVPP,
772 VAProcFilterParameterBufferType,
773 sizeof(deint), 1,
774 &deint, &m_deintFilterID);
775 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
776
777 m_filterBufs[m_numFilterBufs++] = m_deintFilterID;
778 }
779 }
780
781 if (pParams->bEnableProcAmp)
782 {
783 /* Buffer was created earlier and it's time to refresh its value */
784 mfxSts = RemoveBufferFromPipe(m_procampFilterID);
785 MFX_CHECK_STS(mfxSts);
786 }
787
788 if (VA_INVALID_ID == m_procampFilterID)
789 {
790 if ( pParams->bEnableProcAmp )
791 {
792 VAProcFilterParameterBufferColorBalance procamp[4];
793
794 procamp[0].type = VAProcFilterColorBalance;
795 procamp[0].attrib = VAProcColorBalanceBrightness;
796 procamp[0].value = 0;
797
798 if ( pParams->Brightness)
799 {
800 procamp[0].value = convertValue(-100,
801 100,
802 m_procampCaps[VAProcColorBalanceBrightness-1].range.min_value,
803 m_procampCaps[VAProcColorBalanceBrightness-1].range.max_value,
804 pParams->Brightness);
805 }
806
807 procamp[1].type = VAProcFilterColorBalance;
808 procamp[1].attrib = VAProcColorBalanceContrast;
809 procamp[1].value = 1;
810
811 if ( pParams->Contrast != 1 )
812 {
813 procamp[1].value = convertValue(0,
814 10,
815 m_procampCaps[VAProcColorBalanceContrast-1].range.min_value,
816 m_procampCaps[VAProcColorBalanceContrast-1].range.max_value,
817 pParams->Contrast);
818 }
819
820 procamp[2].type = VAProcFilterColorBalance;
821 procamp[2].attrib = VAProcColorBalanceHue;
822 procamp[2].value = 0;
823
824 if ( pParams->Hue)
825 {
826 procamp[2].value = convertValue(-180,
827 180,
828 m_procampCaps[VAProcColorBalanceHue-1].range.min_value,
829 m_procampCaps[VAProcColorBalanceHue-1].range.max_value,
830 pParams->Hue);
831 }
832
833 procamp[3].type = VAProcFilterColorBalance;
834 procamp[3].attrib = VAProcColorBalanceSaturation;
835 procamp[3].value = 1;
836
837 if ( pParams->Saturation != 1 )
838 {
839 procamp[3].value = convertValue(0,
840 10,
841 m_procampCaps[VAProcColorBalanceSaturation-1].range.min_value,
842 m_procampCaps[VAProcColorBalanceSaturation-1].range.max_value,
843 pParams->Saturation);
844 }
845
846 vaSts = vaCreateBuffer((void*)m_vaDisplay,
847 m_vaContextVPP,
848 VAProcFilterParameterBufferType,
849 sizeof(procamp), 4,
850 &procamp, &m_procampFilterID);
851 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
852
853 m_filterBufs[m_numFilterBufs++] = m_procampFilterID;
854
855 /* Clear enable flag. Since appropriate buffer has been created,
856 * it will be used in consequent Execute calls.
857 * If application will Reset or call Init/Close with setting procamp
858 * with new value, this flag will be raised again thus new buffer with
859 * new value will be created. */
860 pParams->bEnableProcAmp = false;
861 }
862 }
863
864 if (pParams->denoiseFactor || pParams->bDenoiseAutoAdjust)
865 {
866 /* Buffer was created earlier and it's time to refresh its value */
867 mfxSts = RemoveBufferFromPipe(m_denoiseFilterID);
868 MFX_CHECK_STS(mfxSts);
869 }
870
871 if (VA_INVALID_ID == m_denoiseFilterID)
872 {
873 if (pParams->denoiseFactor || pParams->bDenoiseAutoAdjust)
874 {
875 VAProcFilterParameterBuffer denoise;
876 denoise.type = VAProcFilterNoiseReduction;
877 if(pParams->bDenoiseAutoAdjust)
878 denoise.value = m_denoiseCaps.range.default_value;
879 else
880 denoise.value = (mfxU16)floor(
881 convertValue(0,
882 100,
883 m_denoiseCaps.range.min_value,
884 m_denoiseCaps.range.max_value,
885 pParams->denoiseFactor) + 0.5);
886 vaSts = vaCreateBuffer((void*)m_vaDisplay,
887 m_vaContextVPP,
888 VAProcFilterParameterBufferType,
889 sizeof(denoise), 1,
890 &denoise, &m_denoiseFilterID);
891 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
892
893 m_filterBufs[m_numFilterBufs++] = m_denoiseFilterID;
894 pParams->denoiseFactor = 0;
895 pParams->bDenoiseAutoAdjust = false;
896 }
897 }
898
899 if (pParams->detailFactor || pParams->bDetailAutoAdjust)
900 {
901 /* Buffer was created earlier and it's time to refresh its value */
902 mfxSts = RemoveBufferFromPipe(m_detailFilterID);
903 MFX_CHECK_STS(mfxSts);
904 }
905
906 if (VA_INVALID_ID == m_detailFilterID)
907 {
908 if (pParams->detailFactor || pParams->bDetailAutoAdjust)
909 {
910 VAProcFilterParameterBuffer detail;
911 detail.type = VAProcFilterSharpening;
912 if(pParams->bDetailAutoAdjust)
913 detail.value = m_detailCaps.range.default_value;
914 else
915 detail.value = (mfxU16)floor(
916 convertValue(0,
917 100,
918 m_detailCaps.range.min_value,
919 m_detailCaps.range.max_value,
920 pParams->detailFactor) + 0.5);
921 vaSts = vaCreateBuffer((void*)m_vaDisplay,
922 m_vaContextVPP,
923 VAProcFilterParameterBufferType,
924 sizeof(detail), 1,
925 &detail, &m_detailFilterID);
926 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
927
928 m_filterBufs[m_numFilterBufs++] = m_detailFilterID;
929 pParams->detailFactor = 0;
930 pParams->bDetailAutoAdjust = false;
931 }
932 }
933
934 if (VA_INVALID_ID == m_frcFilterID)
935 {
936 if (pParams->bFRCEnable)
937 {
938 #ifdef MFX_ENABLE_VPP_FRC
939 VAProcFilterParameterBufferFrameRateConversion frcParams;
940
941 memset(&frcParams, 0, sizeof(VAProcFilterParameterBufferFrameRateConversion));
942 frcParams.type = VAProcFilterFrameRateConversion;
943 if (30 == pParams->customRateData.customRate.FrameRateExtD)
944 {
945 frcParams.input_fps = 30;
946 frcParams.output_fps = 60;
947 frcParams.num_output_frames = 2;
948 frcParams.repeat_frame = 0;
949 }
950 else if (24 == pParams->customRateData.customRate.FrameRateExtD)
951 {
952 frcParams.input_fps = 24;
953 frcParams.output_fps = 60;
954 frcParams.num_output_frames = 5;
955 frcParams.repeat_frame = 0;
956 }
957
958 frcParams.cyclic_counter = m_frcCyclicCounter++;
959 if ((frcParams.input_fps == 30) && (m_frcCyclicCounter == 2))
960 m_frcCyclicCounter = 0;
961 if ((frcParams.input_fps == 24) && (m_frcCyclicCounter == 5))
962 m_frcCyclicCounter = 0;
963 frcParams.output_frames = (VASurfaceID*)(pParams->targetSurface.hdl.first);
964 vaSts = vaCreateBuffer((void*)m_vaDisplay,
965 m_vaContextVPP,
966 VAProcFilterParameterBufferType,
967 sizeof(frcParams), 1,
968 &frcParams, &m_frcFilterID);
969 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
970
971 m_filterBufs[m_numFilterBufs++] = m_frcFilterID;
972 #else
973 return MFX_ERR_UNSUPPORTED;
974 #endif
975 }
976 }
977
978 /* pParams->refCount is total number of processing surfaces:
979 * in case of composition this is primary + sub streams*/
980
981 m_pipelineParam.resize(pParams->refCount);
982 m_pipelineParamID.resize(pParams->refCount, VA_INVALID_ID);
983
984 mfxDrvSurface* pRefSurf = &(pParams->pRefSurfaces[0]);
985 memset(&m_pipelineParam[0], 0, sizeof(m_pipelineParam[0]));
986
987 if (pParams->bFieldWeaving || ( (pParams->refCount > 1) && (0 != pParams->iDeinterlacingAlgorithm )))
988 {
989 m_pipelineParam[0].num_backward_references = 1;
990 mfxDrvSurface* pRefSurf_1 = NULL;
991 /* in pRefSurfaces
992 * first is backward references
993 * then current src surface
994 * and only after this is forward references
995 * */
996 pRefSurf_1 = &(pParams->pRefSurfaces[0]); // point to previous frame
997 VASurfaceID *ref_srf = (VASurfaceID *)(pRefSurf_1->hdl.first);
998 m_pipelineParam[0].backward_references = ref_srf;
999 }
1000 /* FRC Interpolated case */
1001 if (0 != pParams->bFRCEnable)
1002 {
1003 if (30 == pParams->customRateData.customRate.FrameRateExtD)
1004 m_pipelineParam[0].num_forward_references = 2;
1005 else if (24 == pParams->customRateData.customRate.FrameRateExtD)
1006 m_pipelineParam[0].num_forward_references = 3;
1007
1008 if (2 == pParams->refCount) /* may be End of Stream case */
1009 {
1010 mfxDrvSurface* pRefSurf_frc1;
1011 pRefSurf_frc1 = &(pParams->pRefSurfaces[1]);
1012 m_refForFRC[0] = *(VASurfaceID*)(pRefSurf_frc1->hdl.first);
1013 m_refForFRC[2] = m_refForFRC[1] = m_refForFRC[0];
1014 }
1015 if (3 == pParams->refCount)
1016 {
1017 mfxDrvSurface* pRefSurf_frc1;
1018 pRefSurf_frc1 = &(pParams->pRefSurfaces[1]);
1019 m_refForFRC[0] = *(VASurfaceID*)(pRefSurf_frc1->hdl.first);
1020 mfxDrvSurface* pRefSurf_frc2;
1021 pRefSurf_frc2 = &(pParams->pRefSurfaces[2]);
1022 m_refForFRC[1] = *(VASurfaceID*) (pRefSurf_frc2->hdl.first);
1023 }
1024 if (4 == pParams->refCount)
1025 {
1026 mfxDrvSurface* pRefSurf_frc1;
1027 pRefSurf_frc1 = &(pParams->pRefSurfaces[1]);
1028 m_refForFRC[0] = *(VASurfaceID*)(pRefSurf_frc1->hdl.first);
1029 mfxDrvSurface* pRefSurf_frc2;
1030 pRefSurf_frc2 = &(pParams->pRefSurfaces[2]);
1031 m_refForFRC[1] = *(VASurfaceID*) (pRefSurf_frc2->hdl.first);
1032 mfxDrvSurface* pRefSurf_frc3;
1033 pRefSurf_frc3 = &(pParams->pRefSurfaces[3]);
1034 m_refForFRC[2] = *(VASurfaceID*) (pRefSurf_frc3->hdl.first);
1035 }
1036 /* to pass ref list to pipeline */
1037 m_pipelineParam[0].forward_references = m_refForFRC;
1038 } /*if (0 != pParams->bFRCEnable)*/
1039
1040 /* SRC surface */
1041 mfxDrvSurface* pSrcInputSurf = &pRefSurf[pParams->bkwdRefCount];
1042 /* in 30i->60p mode, when scene change occurs, BOB is used and needs current input frame.
1043 * Current frame = ADI reference for odd output frames
1044 * Current frame = ADI input for even output frames
1045 * when mixed picture is progressive, even frame use reference frame for output due to ADI delay
1046 **/
1047 if(pParams->bDeinterlace30i60p && ((VPP_SCENE_NEW == pParams->scene)|| (pParams->iDeinterlacingAlgorithm == 0)))
1048 {
1049 if(m_deintFrameCount % 2)
1050 pSrcInputSurf = &(pParams->pRefSurfaces[0]); // point to reference frame
1051 }
1052
1053 VASurfaceID *srf = (VASurfaceID *)(pSrcInputSurf->hdl.first);
1054 m_pipelineParam[0].surface = *srf;
1055
1056 #ifdef MFX_ENABLE_VPP_ROTATION
1057 switch (pParams->rotation)
1058 {
1059 case MFX_ANGLE_90:
1060 if ( m_pipelineCaps.rotation_flags & (1 << VA_ROTATION_90))
1061 {
1062 m_pipelineParam[0].rotation_state = VA_ROTATION_90;
1063 }
1064 break;
1065 case MFX_ANGLE_180:
1066 if ( m_pipelineCaps.rotation_flags & (1 << VA_ROTATION_180))
1067 {
1068 m_pipelineParam[0].rotation_state = VA_ROTATION_180;
1069 }
1070 break;
1071 case MFX_ANGLE_270:
1072 if ( m_pipelineCaps.rotation_flags & (1 << VA_ROTATION_270))
1073 {
1074 m_pipelineParam[0].rotation_state = VA_ROTATION_270;
1075 }
1076 break;
1077 }
1078 #endif
1079
1080 /*
1081 * Execute mirroring for MIRROR_WO_EXEC only because MSDK will do
1082 * copy-with-mirror for others.
1083 */
1084 if (pParams->mirroringPosition == MIRROR_WO_EXEC) {
1085 switch (pParams->mirroring) {
1086 case MFX_MIRRORING_HORIZONTAL:
1087 m_pipelineParam[0].mirror_state = VA_MIRROR_HORIZONTAL;
1088 break;
1089
1090 case MFX_MIRRORING_VERTICAL:
1091 m_pipelineParam[0].mirror_state = VA_MIRROR_VERTICAL;
1092 break;
1093 }
1094 }
1095
1096 // source cropping
1097 mfxFrameInfo *inInfo = &(pRefSurf->frameInfo);
1098 input_region.y = inInfo->CropY;
1099 input_region.x = inInfo->CropX;
1100 input_region.height = inInfo->CropH;
1101 input_region.width = inInfo->CropW;
1102 m_pipelineParam[0].surface_region = &input_region;
1103
1104 // destination cropping
1105 mfxFrameInfo *outInfo = &(pParams->targetSurface.frameInfo);
1106 output_region.y = outInfo->CropY;
1107 output_region.x = outInfo->CropX;
1108 output_region.height= outInfo->CropH;
1109 output_region.width = outInfo->CropW;
1110 m_pipelineParam[0].output_region = &output_region;
1111
1112 m_pipelineParam[0].output_background_color = 0xff000000; // black for ARGB
1113
1114 #ifdef MFX_ENABLE_VPP_VIDEO_SIGNAL
1115 #define ENABLE_VPP_VIDEO_SIGNAL(X) X
1116 #else
1117 #define ENABLE_VPP_VIDEO_SIGNAL(X)
1118 #endif
1119
1120 mfxU32 refFourcc = pRefSurf->frameInfo.FourCC;
1121 switch (refFourcc)
1122 {
1123 case MFX_FOURCC_RGB4:
1124 #ifdef MFX_ENABLE_RGBP
1125 case MFX_FOURCC_RGBP:
1126 #endif
1127 #if (MFX_VERSION >= 1028)
1128 case MFX_FOURCC_RGB565:
1129 #endif
1130 m_pipelineParam[0].surface_color_standard = VAProcColorStandardNone;
1131 ENABLE_VPP_VIDEO_SIGNAL(m_pipelineParam[0].input_color_properties.color_range = VA_SOURCE_RANGE_FULL);
1132 break;
1133 case MFX_FOURCC_NV12:
1134 default:
1135 m_pipelineParam[0].surface_color_standard = VAProcColorStandardBT601;
1136 ENABLE_VPP_VIDEO_SIGNAL(m_pipelineParam[0].input_color_properties.color_range = VA_SOURCE_RANGE_REDUCED);
1137 break;
1138 }
1139
1140 mfxU32 targetFourcc = pParams->targetSurface.frameInfo.FourCC;
1141 switch (targetFourcc)
1142 {
1143 case MFX_FOURCC_RGB4:
1144 #ifdef MFX_ENABLE_RGBP
1145 case MFX_FOURCC_RGBP:
1146 #endif
1147 #if (MFX_VERSION >= 1028)
1148 case MFX_FOURCC_RGB565:
1149 #endif
1150 m_pipelineParam[0].output_color_standard = VAProcColorStandardNone;
1151 ENABLE_VPP_VIDEO_SIGNAL(m_pipelineParam[0].output_color_properties.color_range = VA_SOURCE_RANGE_FULL);
1152 break;
1153 case MFX_FOURCC_NV12:
1154 m_pipelineParam[0].output_color_standard = VAProcColorStandardBT601;
1155 if(refFourcc == MFX_FOURCC_RGBP)
1156 {
1157 ENABLE_VPP_VIDEO_SIGNAL(m_pipelineParam[0].output_color_properties.color_range = VA_SOURCE_RANGE_FULL);
1158 }
1159 else
1160 {
1161 ENABLE_VPP_VIDEO_SIGNAL(m_pipelineParam[0].output_color_properties.color_range = VA_SOURCE_RANGE_REDUCED);
1162 }
1163 break;
1164 default:
1165 m_pipelineParam[0].output_color_standard = VAProcColorStandardBT601;
1166 ENABLE_VPP_VIDEO_SIGNAL(m_pipelineParam[0].output_color_properties.color_range = VA_SOURCE_RANGE_REDUCED);
1167 break;
1168 }
1169
1170 m_pipelineParam[0].input_color_properties.chroma_sample_location = VA_CHROMA_SITING_UNKNOWN;
1171 m_pipelineParam[0].output_color_properties.chroma_sample_location = VA_CHROMA_SITING_UNKNOWN;
1172
1173 /* It needs interlaced flag passed only for
1174 * deinterlacing and scaling. All other filters must
1175 * use progressive even for interlaced content.
1176 */
1177 bool forceProgressive = true;
1178 if (pParams->iDeinterlacingAlgorithm ||
1179 inInfo->CropH != outInfo->CropH ||
1180 inInfo->CropW != outInfo->CropW)
1181 {
1182 forceProgressive = false;
1183 }
1184
1185 switch (pRefSurf->frameInfo.PicStruct)
1186 {
1187 case MFX_PICSTRUCT_PROGRESSIVE:
1188 m_pipelineParam[0].filter_flags = VA_FRAME_PICTURE;
1189 break;
1190 case MFX_PICSTRUCT_FIELD_TFF:
1191 m_pipelineParam[0].filter_flags = forceProgressive ? VA_FRAME_PICTURE : VA_TOP_FIELD;
1192 break;
1193 case MFX_PICSTRUCT_FIELD_BFF:
1194 m_pipelineParam[0].filter_flags = forceProgressive ? VA_FRAME_PICTURE : VA_BOTTOM_FIELD;
1195 break;
1196 }
1197
1198 if (pParams->bFieldWeaving)
1199 {
1200 // Field weaving needs flags that are different from usual pipeline
1201 switch (pRefSurf->frameInfo.PicStruct)
1202 {
1203 case MFX_PICSTRUCT_FIELD_TFF:
1204 m_pipelineParam[0].filter_flags = VA_TOP_FIELD_WEAVE;
1205 break;
1206 case MFX_PICSTRUCT_FIELD_BFF:
1207 m_pipelineParam[0].filter_flags = VA_BOTTOM_FIELD_WEAVE;
1208 break;
1209 }
1210 }
1211
1212 m_pipelineParam[0].filters = m_filterBufs;
1213 m_pipelineParam[0].num_filters = m_numFilterBufs;
1214
1215 int index = GetCurFrameSignalIdx(pParams);
1216 if ((index >= 0) && pParams->VideoSignalInfo[index].enabled)
1217 {
1218 #ifdef MFX_ENABLE_VPP_VIDEO_SIGNAL
1219 if(pParams->VideoSignalInfo[index].TransferMatrix != MFX_TRANSFERMATRIX_UNKNOWN)
1220 {
1221 m_pipelineParam[0].surface_color_standard = (MFX_TRANSFERMATRIX_BT709 == pParams->VideoSignalInfo[index].TransferMatrix ? VAProcColorStandardBT709 : VAProcColorStandardBT601);
1222 }
1223
1224 if(pParams->VideoSignalInfo[index].NominalRange != MFX_NOMINALRANGE_UNKNOWN)
1225 {
1226 m_pipelineParam[0].input_color_properties.color_range = (MFX_NOMINALRANGE_0_255 == pParams->VideoSignalInfo[index].NominalRange) ? VA_SOURCE_RANGE_FULL : VA_SOURCE_RANGE_REDUCED;
1227 }
1228 }
1229
1230 if (pParams->VideoSignalInfoOut.enabled)
1231 {
1232 if(pParams->VideoSignalInfoOut.TransferMatrix != MFX_TRANSFERMATRIX_UNKNOWN)
1233 {
1234 m_pipelineParam[0].output_color_standard = (MFX_TRANSFERMATRIX_BT709 == pParams->VideoSignalInfoOut.TransferMatrix ? VAProcColorStandardBT709 : VAProcColorStandardBT601);
1235 }
1236
1237 if(pParams->VideoSignalInfoOut.NominalRange != MFX_NOMINALRANGE_UNKNOWN)
1238 {
1239 m_pipelineParam[0].output_color_properties.color_range = (MFX_NOMINALRANGE_0_255 == pParams->VideoSignalInfoOut.NominalRange) ? VA_SOURCE_RANGE_FULL : VA_SOURCE_RANGE_REDUCED;
1240 }
1241 #else
1242 return MFX_ERR_UNSUPPORTED;
1243 #endif // #ifdef MFX_ENABLE_VPP_VIDEO_SIGNAL
1244 }
1245
1246 m_pipelineParam[0].input_color_properties.chroma_sample_location = VA_CHROMA_SITING_UNKNOWN;
1247 m_pipelineParam[0].output_color_properties.chroma_sample_location = VA_CHROMA_SITING_UNKNOWN;
1248
1249 /* Scaling params */
1250 switch (pParams->scalingMode)
1251 {
1252 case MFX_SCALING_MODE_LOWPOWER:
1253 /* VA_FILTER_SCALING_DEFAULT means the following:
1254 * First priority is HW fixed function scaling engine. If it can't work, revert to AVS
1255 * If scaling ratio between 1/8...8 -> HW fixed function
1256 * If scaling ratio between 1/16...1/8 or larger than 8 -> AVS
1257 * If scaling ratio is less than 1/16 -> bilinear
1258 */
1259 m_pipelineParam[0].filter_flags |= VA_FILTER_SCALING_DEFAULT;
1260 break;
1261 case MFX_SCALING_MODE_QUALITY:
1262 /* VA_FILTER_SCALING_HQ means the following:
1263 * If scaling ratio is less than 1/16 -> bilinear
1264 * For all other cases, AVS is used.
1265 */
1266 m_pipelineParam[0].filter_flags |= VA_FILTER_SCALING_HQ;
1267 break;
1268 case MFX_SCALING_MODE_DEFAULT:
1269 default:
1270 if(MFX_HW_APL == hwType)
1271 {
1272 /* Use HW fixed function scaling engine by default on APL due to power consumption considerations */
1273 m_pipelineParam[0].filter_flags |= VA_FILTER_SCALING_DEFAULT;
1274 }
1275 else
1276 {
1277 /* Force AVS by default for all platforms except BXT */
1278 m_pipelineParam[0].filter_flags |= VA_FILTER_SCALING_HQ;
1279 }
1280 break;
1281 }
1282
1283 #if (MFX_VERSION >= 1025)
1284 uint8_t& chromaSitingMode = m_pipelineParam[0].input_color_properties.chroma_sample_location;
1285 chromaSitingMode = VA_CHROMA_SITING_UNKNOWN;
1286
1287 switch (pParams->chromaSiting)
1288 {
1289 case MFX_CHROMA_SITING_HORIZONTAL_LEFT | MFX_CHROMA_SITING_VERTICAL_TOP:
1290 //Option A : Chroma samples are aligned horizontally and vertically with multiples of the luma samples
1291 chromaSitingMode = VA_CHROMA_SITING_HORIZONTAL_LEFT | VA_CHROMA_SITING_VERTICAL_TOP;
1292 break;
1293 case MFX_CHROMA_SITING_HORIZONTAL_LEFT | MFX_CHROMA_SITING_VERTICAL_CENTER:
1294 //Option AB : Chroma samples are vertically centered between, but horizontally aligned with luma samples.
1295 chromaSitingMode = VA_CHROMA_SITING_HORIZONTAL_LEFT | VA_CHROMA_SITING_VERTICAL_CENTER;
1296 break;
1297 case MFX_CHROMA_SITING_HORIZONTAL_LEFT | MFX_CHROMA_SITING_VERTICAL_BOTTOM:
1298 //Option B : Chroma samples are horizontally aligned and vertically 1 pixel offset to the bottom.
1299 chromaSitingMode = VA_CHROMA_SITING_HORIZONTAL_LEFT | VA_CHROMA_SITING_VERTICAL_BOTTOM;
1300 break;
1301 case MFX_CHROMA_SITING_HORIZONTAL_CENTER | MFX_CHROMA_SITING_VERTICAL_CENTER:
1302 //Option ABCD : Chroma samples are centered between luma samples both horizontally and vertically.
1303 chromaSitingMode = VA_CHROMA_SITING_HORIZONTAL_CENTER | VA_CHROMA_SITING_VERTICAL_CENTER;
1304 break;
1305 case MFX_CHROMA_SITING_HORIZONTAL_CENTER | MFX_CHROMA_SITING_VERTICAL_TOP:
1306 //Option AC : Chroma samples are vertically aligned with, and horizontally centered between luma
1307 chromaSitingMode = VA_CHROMA_SITING_HORIZONTAL_CENTER | VA_CHROMA_SITING_VERTICAL_TOP;
1308 break;
1309 case MFX_CHROMA_SITING_HORIZONTAL_CENTER | MFX_CHROMA_SITING_VERTICAL_BOTTOM:
1310 //Option BD : Chroma samples are horizontally 0.5 pixel offset to the right and vertically 1 pixel offset to the bottom.
1311 chromaSitingMode = VA_CHROMA_SITING_HORIZONTAL_CENTER | VA_CHROMA_SITING_VERTICAL_BOTTOM;
1312 break;
1313 case MFX_CHROMA_SITING_UNKNOWN:
1314 default:
1315 break;
1316 }
1317 m_pipelineParam[0].output_color_properties.chroma_sample_location = chromaSitingMode;
1318 #endif
1319
1320 if (pParams->mirroringExt)
1321 {
1322 // First priority is HW fixed function scaling engine. If it can't work, revert to AVS
1323 // Starting from ATS there is only HW fixed function scaling engine due to AVS removal
1324 m_pipelineParam[0].filter_flags = VA_FILTER_SCALING_DEFAULT;
1325
1326 switch (pParams->mirroring)
1327 {
1328 case MFX_MIRRORING_VERTICAL:
1329 m_pipelineParam[0].mirror_state = VA_MIRROR_VERTICAL;
1330 break;
1331 case MFX_MIRRORING_HORIZONTAL:
1332 m_pipelineParam[0].mirror_state = VA_MIRROR_HORIZONTAL;
1333 break;
1334 }
1335 }
1336
1337 vaSts = vaCreateBuffer(m_vaDisplay,
1338 m_vaContextVPP,
1339 VAProcPipelineParameterBufferType,
1340 sizeof(VAProcPipelineParameterBuffer),
1341 1,
1342 &m_pipelineParam[0],
1343 &m_pipelineParamID[0]);
1344 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1345
1346 // increase deinterlacer frame count after frame has been processed
1347 m_deintFrameCount ++;
1348
1349 // for ADI 30i->60p, EOS is received on second field after vpp_reset
1350 // reset m_deintFrameCount to zero after processing second field
1351 if((pParams->bEOS) && (pParams->bDeinterlace30i60p == true))
1352 m_deintFrameCount = 0;
1353
1354 VASurfaceID *outputSurface = (VASurfaceID*)(pParams->targetSurface.hdl.first);
1355
1356 //create gpu priority buffer and bufferID
1357 if(m_MaxContextPriority)
1358 {
1359 mfxPriority contextPriority = m_core->GetSession()->m_priority;
1360 VAContextParameterUpdateBuffer GpuPriorityBuf_vpp;
1361 memset(&GpuPriorityBuf_vpp, 0, sizeof(VAContextParameterUpdateBuffer));
1362
1363 GpuPriorityBuf_vpp.flags.bits.context_priority_update = 1;
1364 if(contextPriority == MFX_PRIORITY_LOW)
1365 {
1366 GpuPriorityBuf_vpp.context_priority.bits.priority = 0;
1367 }
1368 else if (contextPriority == MFX_PRIORITY_HIGH)
1369 {
1370 GpuPriorityBuf_vpp.context_priority.bits.priority = m_MaxContextPriority;
1371 }
1372 else
1373 {
1374 GpuPriorityBuf_vpp.context_priority.bits.priority = m_MaxContextPriority/2;
1375 }
1376
1377 vaSts = vaCreateBuffer((void*)m_vaDisplay,
1378 m_vaContextVPP,
1379 VAContextParameterUpdateBufferType,
1380 sizeof(GpuPriorityBuf_vpp), 1,
1381 &GpuPriorityBuf_vpp, &m_gpuPriorityID);
1382 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1383 }
1384
1385 MFX_LTRACE_2(MFX_TRACE_LEVEL_HOTSPOTS, "A|VPP|FILTER|PACKET_START|", "%d|%d", m_vaContextVPP, 0);
1386 {
1387 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaBeginPicture");
1388 vaSts = vaBeginPicture(m_vaDisplay,
1389 m_vaContextVPP,
1390 *outputSurface);
1391 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1392 }
1393
1394 if(m_MaxContextPriority)
1395 {
1396 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaRenderPicture_gpuPriority");
1397 vaSts = vaRenderPicture(m_vaDisplay, m_vaContextVPP, &m_gpuPriorityID, 1);
1398 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1399 }
1400
1401 {
1402 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaRenderPicture");
1403 vaSts = vaRenderPicture(m_vaDisplay, m_vaContextVPP, &m_pipelineParamID[0], 1);
1404 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1405 }
1406
1407 {
1408 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaEndPicture");
1409 vaSts = vaEndPicture(m_vaDisplay, m_vaContextVPP);
1410 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1411 }
1412 MFX_LTRACE_2(MFX_TRACE_LEVEL_HOTSPOTS, "A|VPP|FILTER|PACKET_END|", "%d|%d", m_vaContextVPP, 0);
1413
1414 for (VABufferID& id : m_pipelineParamID)
1415 {
1416 mfxSts = CheckAndDestroyVAbuffer(m_vaDisplay, id);
1417 MFX_CHECK_STS(mfxSts);
1418 }
1419
1420 if(m_MaxContextPriority)
1421 {
1422 mfxSts = CheckAndDestroyVAbuffer(m_vaDisplay, m_gpuPriorityID);
1423 MFX_CHECK_STS(mfxSts);
1424 }
1425
1426 mfxSts = RemoveBufferFromPipe(m_deintFilterID);
1427 MFX_CHECK_STS(mfxSts);
1428
1429 // (3) info needed for sync operation
1430 //-------------------------------------------------------
1431 {
1432 UMC::AutomaticUMCMutex guard(m_guard);
1433
1434 ExtVASurface currentFeedback; // {surface & number_of_task}
1435 currentFeedback.surface = *outputSurface;
1436 currentFeedback.number = pParams->statusReportID;
1437 m_feedbackCache.push_back(currentFeedback);
1438 }
1439
1440 mfxSts = RemoveBufferFromPipe(m_frcFilterID);
1441 MFX_CHECK_STS(mfxSts);
1442
1443 return MFX_ERR_NONE;
1444 } // mfxStatus VAAPIVideoProcessing::Execute(FASTCOMP_BLT_PARAMS *pVideoCompositingBlt)
1445
RemoveBufferFromPipe(VABufferID & id)1446 mfxStatus VAAPIVideoProcessing::RemoveBufferFromPipe(VABufferID& id)
1447 {
1448 if (id != VA_INVALID_ID)
1449 {
1450 VABufferID tmp = id;
1451 mfxStatus sts = CheckAndDestroyVAbuffer(m_vaDisplay, id);
1452 MFX_CHECK_STS(sts);
1453
1454 std::remove(m_filterBufs, m_filterBufs + m_numFilterBufs, tmp);
1455 m_filterBufs[m_numFilterBufs] = VA_INVALID_ID;
1456 --m_numFilterBufs;
1457 }
1458
1459 return MFX_ERR_NONE;
1460 }
1461
1462
isVideoWall(mfxExecuteParams * pParams)1463 BOOL VAAPIVideoProcessing::isVideoWall(mfxExecuteParams *pParams)
1464 {
1465 BOOL result = false;
1466 mfxU16 outputWidth;
1467 mfxU16 outputHeight;
1468 mfxU16 layerWidth = 0;
1469 mfxU16 layerHeight = 0;
1470 mfxU16 numX = 0;
1471 mfxU16 numY = 0;
1472 std::vector <mfxU32> indexVW;
1473 std::map<mfxU16, compStreamElem> layout;
1474
1475 mfxU32 layerCount = (mfxU32) pParams->fwdRefCount + 1;
1476
1477 if ( layerCount % MAX_STREAMS_PER_TILE != 0 )
1478 {
1479 /* Number of streams must be multiple of 8. That's just for simplicity.
1480 * TODO: need to handle the case when number is not multiple of 8*/
1481 return result;
1482 }
1483
1484 indexVW.reserve(layerCount);
1485 outputWidth = pParams->targetSurface.frameInfo.CropW;
1486 outputHeight = pParams->targetSurface.frameInfo.CropH;
1487
1488 /**/
1489 layerWidth = pParams->dstRects[0].DstW;
1490 numX = outputWidth / layerWidth;
1491 layerHeight = pParams->dstRects[0].DstH;
1492 numY = outputHeight / layerHeight;
1493
1494 // Set up perfect layout of the video wall
1495 for ( unsigned int j = 0; j < layerCount; j++ )
1496 {
1497 mfxU16 render_order = (j/numX)*numX + (j % numX);
1498 compStreamElem element;
1499 element.x = (j % numX)*layerWidth;
1500 element.y = (j/numX)*layerHeight;
1501 layout.insert(std::pair<mfxU16, compStreamElem>(render_order, element));
1502 }
1503
1504 for ( unsigned int i = 0; i < layerCount; i++)
1505 {
1506 std::map<mfxU16, compStreamElem>::iterator it;
1507 DstRect rect = pParams->dstRects[i];
1508
1509 if ( outputWidth % rect.DstW != 0 )
1510 {
1511 /* Layer width should fit output */
1512 return result;
1513 }
1514
1515 if ( layerWidth != rect.DstW)
1516 {
1517 /* All layers must have the same width */
1518 return result;
1519 }
1520
1521 if ( outputHeight % rect.DstH != 0 )
1522 {
1523 /* Layer height should fit output */
1524 return result;
1525 }
1526
1527 if ( layerHeight != rect.DstH)
1528 {
1529 /* All layers must have the same height */
1530 return result;
1531 }
1532
1533 mfxU16 render_order = 0;
1534 render_order = rect.DstX/(outputWidth/numX);
1535 render_order += numX * (rect.DstY/(outputHeight/numY));
1536 it = layout.find(render_order);
1537 if ( layout.end() == it )
1538 {
1539 /* All layers must have the same height */
1540 return result;
1541 }
1542 else if (it->second.active)
1543 {
1544 /* Slot is busy with another layer already */
1545 return result;
1546 }
1547 else if (it->second.x != rect.DstX || it->second.y != rect.DstY)
1548 {
1549 /* Layers should be ordered in proper way allowing partial rendering on output */
1550 return result;
1551 }
1552 else
1553 {
1554 it->second.active = true;
1555 it->second.index = i;
1556 indexVW.push_back(render_order);
1557 }
1558 }
1559
1560 if ( numX > 1 && numX % 2 != 0 )
1561 {
1562 /* Number of layers on X-axis is not correct */
1563 return result;
1564 }
1565
1566 if ( numY % 2 != 0 )
1567 {
1568 /* Number of layers on Y-axis is not correct */
1569 return result;
1570 }
1571
1572 result = true;
1573
1574 pParams->iTilesNum4Comp = layerCount / MAX_STREAMS_PER_TILE;
1575 for ( unsigned int i = 0; i < layerCount; i++)
1576 {
1577 pParams->dstRects[i].TileId = indexVW[i] / MAX_STREAMS_PER_TILE;
1578 }
1579
1580 return result;
1581 }
1582
1583 #ifdef MFX_ENABLE_VPP_COMPOSITION
Execute_Composition_TiledVideoWall(mfxExecuteParams * pParams)1584 mfxStatus VAAPIVideoProcessing::Execute_Composition_TiledVideoWall(mfxExecuteParams *pParams)
1585 {
1586 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_HOTSPOTS, "VAAPIVideoProcessing::Execute_Composition_TiledVideoWall");
1587
1588 mfxStatus sts;
1589 VAStatus vaSts = VA_STATUS_SUCCESS;
1590 std::vector<VABlendState> blend_state;
1591
1592 MFX_CHECK_NULL_PTR1( pParams );
1593 MFX_CHECK_NULL_PTR1( pParams->targetSurface.hdl.first );
1594 MFX_CHECK_NULL_PTR1( pParams->pRefSurfaces );
1595 MFX_CHECK_NULL_PTR1( pParams->pRefSurfaces[0].hdl.first );
1596
1597 if ( 0 == pParams->iTilesNum4Comp )
1598 {
1599 return MFX_ERR_UNKNOWN;
1600 }
1601 mfxU32 layerCount = (mfxU32) pParams->fwdRefCount + 1;
1602
1603 std::vector<m_tiledVideoWallParams> tilingParams;
1604 tilingParams.resize(pParams->iTilesNum4Comp);
1605 for ( unsigned int i = 0; i < tilingParams.size(); i++)
1606 {
1607 tilingParams[i].targerRect.x = tilingParams[i].targerRect.y = 0x7fff;
1608 tilingParams[i].targerRect.width = tilingParams[i].targerRect.height = 0;
1609 }
1610
1611 m_pipelineParam.resize(pParams->refCount + 1);
1612 m_pipelineParamID.resize(pParams->refCount + 1, VA_INVALID_ID);
1613 blend_state.resize(pParams->refCount + 1);
1614
1615 std::vector<VARectangle> input_region;
1616 input_region.resize(pParams->refCount + 1);
1617 std::vector<VARectangle> output_region;
1618 output_region.resize(pParams->refCount + 1);
1619
1620 /* Initial set up for layers */
1621 for ( unsigned int i = 0; i < layerCount; i++)
1622 {
1623 mfxDrvSurface* pRefSurf = &(pParams->pRefSurfaces[i]);
1624 VASurfaceID* srf = (VASurfaceID*)(pRefSurf->hdl.first);
1625
1626 m_pipelineParam[i].surface = *srf;
1627
1628 // source cropping
1629 mfxU32 refFourcc = pRefSurf->frameInfo.FourCC;
1630 switch (refFourcc)
1631 {
1632 case MFX_FOURCC_RGB4:
1633 m_pipelineParam[i].surface_color_standard = VAProcColorStandardNone;
1634 break;
1635 case MFX_FOURCC_NV12:
1636 default:
1637 m_pipelineParam[i].surface_color_standard = VAProcColorStandardBT601;
1638 break;
1639 }
1640
1641 mfxU32 targetFourcc = pParams->targetSurface.frameInfo.FourCC;
1642 switch (targetFourcc)
1643 {
1644 case MFX_FOURCC_RGB4:
1645 m_pipelineParam[i].output_color_standard = VAProcColorStandardNone;
1646 break;
1647 case MFX_FOURCC_NV12:
1648 default:
1649 m_pipelineParam[i].output_color_standard = VAProcColorStandardBT601;
1650 break;
1651 }
1652
1653 if(pParams->VideoSignalInfo[i].enabled)
1654 {
1655 if(pParams->VideoSignalInfo[i].TransferMatrix != MFX_TRANSFERMATRIX_UNKNOWN)
1656 {
1657 m_pipelineParam[i].surface_color_standard = (MFX_TRANSFERMATRIX_BT709 == pParams->VideoSignalInfo[i].TransferMatrix) ? VAProcColorStandardBT709 : VAProcColorStandardBT601;
1658 }
1659
1660 if(pParams->VideoSignalInfo[i].NominalRange != MFX_NOMINALRANGE_UNKNOWN)
1661 {
1662 m_pipelineParam[i].input_color_properties.color_range = (MFX_NOMINALRANGE_0_255 == pParams->VideoSignalInfo[i].NominalRange) ? VA_SOURCE_RANGE_FULL : VA_SOURCE_RANGE_REDUCED;
1663 }
1664 }
1665
1666 switch (pRefSurf->frameInfo.PicStruct)
1667 {
1668 case MFX_PICSTRUCT_PROGRESSIVE:
1669 m_pipelineParam[i].filter_flags = VA_FRAME_PICTURE;
1670 break;
1671 case MFX_PICSTRUCT_FIELD_TFF:
1672 m_pipelineParam[i].filter_flags = VA_TOP_FIELD;
1673 break;
1674 case MFX_PICSTRUCT_FIELD_BFF:
1675 m_pipelineParam[i].filter_flags = VA_BOTTOM_FIELD;
1676 break;
1677 }
1678
1679 /* to process input parameters of sub stream:
1680 * crop info and original size*/
1681 mfxFrameInfo *inInfo = &(pRefSurf->frameInfo);
1682 input_region[i].y = inInfo->CropY;
1683 input_region[i].x = inInfo->CropX;
1684 input_region[i].height = inInfo->CropH;
1685 input_region[i].width = inInfo->CropW;
1686 m_pipelineParam[i].surface_region = &input_region[i];
1687
1688 /* to process output parameters of sub stream:
1689 * position and destination size */
1690 output_region[i].y = pParams->dstRects[i].DstY;
1691 output_region[i].x = pParams->dstRects[i].DstX;
1692 output_region[i].height = pParams->dstRects[i].DstH;
1693 output_region[i].width = pParams->dstRects[i].DstW;
1694 m_pipelineParam[i].output_region = &output_region[i];
1695
1696 mfxU32 currTileId = pParams->dstRects[i].TileId;
1697
1698 if (((currTileId > (pParams->iTilesNum4Comp - 1) )) ||
1699 (tilingParams[currTileId].numChannels >=8))
1700 {
1701 // Maximum number channels in tile is 8
1702 // fallback case
1703 return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
1704 }
1705 else
1706 {
1707 tilingParams[currTileId].channelIds[tilingParams[currTileId].numChannels] = i;
1708 tilingParams[currTileId].numChannels++;
1709 /* lets define tiles working rectangle */
1710 if (tilingParams[currTileId].targerRect.x > output_region[i].x)
1711 tilingParams[currTileId].targerRect.x = output_region[i].x;
1712 if (tilingParams[currTileId].targerRect.y > output_region[i].y)
1713 tilingParams[currTileId].targerRect.y = output_region[i].y;
1714 if (tilingParams[currTileId].targerRect.width <
1715 (output_region[i].x + output_region[i].width) )
1716 tilingParams[currTileId].targerRect.width = output_region[i].x + output_region[i].width;
1717 if (tilingParams[currTileId].targerRect.height <
1718 (output_region[i].y + output_region[i].height) )
1719 tilingParams[currTileId].targerRect.height = output_region[i].y + output_region[i].height;
1720 }
1721
1722 /* Global alpha and luma key can not be enabled together*/
1723 if (pParams->dstRects[i].GlobalAlphaEnable !=0)
1724 {
1725 blend_state[i].flags = VA_BLEND_GLOBAL_ALPHA;
1726 blend_state[i].global_alpha = ((float)pParams->dstRects[i].GlobalAlpha) /255;
1727 }
1728 /* Luma color key for YUV surfaces only.
1729 * And Premultiplied alpha blending for RGBA surfaces only.
1730 * So, these two flags can't combine together */
1731 if ((pParams->dstRects[i].LumaKeyEnable != 0) &&
1732 (pParams->dstRects[i].PixelAlphaEnable == 0) )
1733 {
1734 blend_state[i].flags |= VA_BLEND_LUMA_KEY;
1735 blend_state[i].min_luma = ((float)pParams->dstRects[i].LumaKeyMin/255);
1736 blend_state[i].max_luma = ((float)pParams->dstRects[i].LumaKeyMax/255);
1737 }
1738 if ((pParams->dstRects[i].LumaKeyEnable == 0 ) &&
1739 (pParams->dstRects[i].PixelAlphaEnable != 0 ) )
1740 {
1741 blend_state[i].flags |= VA_BLEND_PREMULTIPLIED_ALPHA;
1742 }
1743 if ((pParams->dstRects[i].GlobalAlphaEnable != 0) ||
1744 (pParams->dstRects[i].LumaKeyEnable != 0) ||
1745 (pParams->dstRects[i].PixelAlphaEnable != 0))
1746 {
1747 m_pipelineParam[i].blend_state = &blend_state[i];
1748 }
1749
1750 m_pipelineParam[i].pipeline_flags |= VA_PROC_PIPELINE_SUBPICTURES;
1751 m_pipelineParam[i].filter_flags |= VA_FILTER_SCALING_HQ;
1752
1753 m_pipelineParam[i].filters = 0;
1754 m_pipelineParam[i].num_filters = 0;
1755 m_pipelineParam[i].output_background_color = 0xff000000;
1756
1757 vaSts = vaCreateBuffer(m_vaDisplay,
1758 m_vaContextVPP,
1759 VAProcPipelineParameterBufferType,
1760 sizeof(VAProcPipelineParameterBuffer),
1761 1,
1762 &m_pipelineParam[i],
1763 &m_pipelineParamID[i]);
1764 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1765 }
1766
1767 VASurfaceID *outputSurface = (VASurfaceID*)(pParams->targetSurface.hdl.first);
1768 VAProcPipelineParameterBuffer outputparam = {};
1769 VABufferID vpp_pipeline_outbuf = VA_INVALID_ID;
1770
1771 MFX_CHECK_NULL_PTR1(outputSurface);
1772
1773 /* Process by groups. Video wall case assumes
1774 * that surfaces has the same output dimensions
1775 * We split output by several horizontal tiles */
1776 for (unsigned int currTile = 0; currTile < tilingParams.size(); currTile++)
1777 {
1778 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaBeginPicture");
1779 vaSts = vaBeginPicture(m_vaDisplay,
1780 m_vaContextVPP,
1781 *outputSurface);
1782 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1783
1784 outputparam.surface = *outputSurface;
1785 // The targerRect.width and targerRect.height here actually storing the x2 and y2
1786 // value. Deduct x and y respectively to get the exact targerRect.width and
1787 // targerRect.height
1788 tilingParams[currTile].targerRect.width -= tilingParams[currTile].targerRect.x;
1789 tilingParams[currTile].targerRect.height -= tilingParams[currTile].targerRect.y;
1790
1791 outputparam.output_region = &tilingParams[currTile].targerRect;
1792 outputparam.surface_region = &tilingParams[currTile].targerRect;
1793 outputparam.output_background_color = 0;
1794
1795 vaSts = vaCreateBuffer(m_vaDisplay,
1796 m_vaContextVPP,
1797 VAProcPipelineParameterBufferType,
1798 sizeof(VAProcPipelineParameterBuffer),
1799 1,
1800 &outputparam,
1801 &vpp_pipeline_outbuf);
1802 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1803
1804 vaSts = vaRenderPicture(m_vaDisplay, m_vaContextVPP, &vpp_pipeline_outbuf, 1);
1805 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1806
1807 for (unsigned int i = 0; i < tilingParams[currTile].numChannels; i++)
1808 {
1809 vaSts = vaRenderPicture(m_vaDisplay, m_vaContextVPP, &m_pipelineParamID[tilingParams[currTile].channelIds[i]], 1);
1810 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1811 }
1812 {
1813 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaEndPicture");
1814 vaSts = vaEndPicture(m_vaDisplay, m_vaContextVPP);
1815 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1816 }
1817
1818 sts = CheckAndDestroyVAbuffer(m_vaDisplay, vpp_pipeline_outbuf);
1819 MFX_CHECK_STS(sts);
1820 }
1821
1822 for (VABufferID& id : m_pipelineParamID)
1823 {
1824 sts = CheckAndDestroyVAbuffer(m_vaDisplay, id);
1825 MFX_CHECK_STS(sts);
1826 }
1827
1828 // (3) info needed for sync operation
1829 //-------------------------------------------------------
1830 {
1831 UMC::AutomaticUMCMutex guard(m_guard);
1832
1833 ExtVASurface currentFeedback; // {surface & number_of_task}
1834 currentFeedback.surface = *outputSurface;
1835 currentFeedback.number = pParams->statusReportID;
1836 m_feedbackCache.push_back(currentFeedback);
1837 }
1838
1839 return MFX_ERR_NONE;
1840 } // mfxStatus VAAPIVideoProcessing::Execute_Composition_TileVideoWall(mfxExecuteParams *pParams)
1841
Execute_Composition(mfxExecuteParams * pParams)1842 mfxStatus VAAPIVideoProcessing::Execute_Composition(mfxExecuteParams *pParams)
1843 {
1844 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_HOTSPOTS, "VAAPIVideoProcessing::Execute_Composition");
1845
1846 VAStatus vaSts = VA_STATUS_SUCCESS;
1847 VASurfaceAttrib attrib;
1848 std::vector<VABlendState> blend_state;
1849 VAImage imagePrimarySurface;
1850 mfxU8* pPrimarySurfaceBuffer;
1851
1852 MFX_CHECK_NULL_PTR1( pParams );
1853 MFX_CHECK_NULL_PTR1( pParams->targetSurface.hdl.first );
1854 MFX_CHECK_NULL_PTR1( pParams->pRefSurfaces );
1855 MFX_CHECK_NULL_PTR1( pParams->pRefSurfaces[0].hdl.first );
1856
1857 mfxU32 refCount = (mfxU32) pParams->fwdRefCount;
1858 bool hasResize = false;
1859
1860 for(mfxU32 i = 0; i < refCount; i++)
1861 {
1862 // Check if there is a resize for input streams
1863 mfxFrameInfo *surf_info = &(pParams->pRefSurfaces[i].frameInfo);
1864 if (surf_info->CropW != pParams->dstRects[i].DstW ||
1865 surf_info->CropH != pParams->dstRects[i].DstH){
1866 hasResize = true;
1867 break;
1868 }
1869 }
1870
1871 if ((m_primarySurface4Composition == NULL) && (pParams->bBackgroundRequired))
1872 {
1873 mfxDrvSurface* pRefSurf = &(pParams->targetSurface);
1874 mfxFrameInfo *inInfo = &(pRefSurf->frameInfo);
1875
1876 m_primarySurface4Composition = (VASurfaceID*)calloc(1,1*sizeof(VASurfaceID));
1877 /* required to check, is memory allocated o not */
1878 if (m_primarySurface4Composition == NULL)
1879 return MFX_ERR_MEMORY_ALLOC;
1880
1881 attrib.type = VASurfaceAttribPixelFormat;
1882 attrib.value.type = VAGenericValueTypeInteger;
1883
1884 unsigned int rt_format;
1885
1886 // default format is NV12
1887 if (inInfo->FourCC == MFX_FOURCC_RGB4)
1888 {
1889 attrib.value.value.i = VA_FOURCC_ARGB;
1890 rt_format = VA_RT_FORMAT_RGB32;
1891 }
1892 else if(inInfo->FourCC == MFX_FOURCC_P010
1893 || inInfo->FourCC == MFX_FOURCC_P210
1894 #if (MFX_VERSION >= 1027)
1895 || inInfo->FourCC == MFX_FOURCC_Y210
1896 || inInfo->FourCC == MFX_FOURCC_Y410
1897 #endif
1898 )
1899 {
1900 attrib.value.value.i = VA_FOURCC_P010; // We're going to flood fill this surface, so let's use most common 10-bit format
1901 rt_format = VA_RT_FORMAT_YUV420;
1902 }
1903 #if (MFX_VERSION >= 1031)
1904 else if(inInfo->FourCC == MFX_FOURCC_P016
1905 || inInfo->FourCC == MFX_FOURCC_Y216
1906 || inInfo->FourCC == MFX_FOURCC_Y416
1907 )
1908 {
1909 attrib.value.value.i = VA_FOURCC_P016; // We're going to flood fill this surface, so let's use most common 10-bit format
1910 rt_format = VA_RT_FORMAT_YUV420_10BPP;
1911 }
1912 #endif
1913 else
1914 {
1915 attrib.value.value.i = VA_FOURCC_NV12;
1916 rt_format = VA_RT_FORMAT_YUV420;
1917 }
1918 attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
1919
1920 // Check what resolution is better. If input surfaces are going to be resized, then
1921 // it's better to allocate small surface for background. If there is no resize for
1922 // input streams, then it's better to allocate surface with the resolution equal to
1923 // the output stream to eliminate resize for background surface.
1924 mfxU32 width = hasResize ? VPP_COMP_BACKGROUND_SURFACE_WIDTH : inInfo->Width;
1925 mfxU32 height = hasResize ? VPP_COMP_BACKGROUND_SURFACE_HEIGHT : inInfo->Height;
1926
1927 vaSts = vaCreateSurfaces(m_vaDisplay, rt_format, width, height,
1928 m_primarySurface4Composition, 1, &attrib, 1);
1929 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1930
1931 for ( int iPrSurfCount = 0; iPrSurfCount < 1; iPrSurfCount++)
1932 {
1933 vaSts = vaDeriveImage(m_vaDisplay, m_primarySurface4Composition[iPrSurfCount], &imagePrimarySurface);
1934 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1935
1936 vaSts = vaMapBuffer(m_vaDisplay, imagePrimarySurface.buf, (void **) &pPrimarySurfaceBuffer);
1937 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
1938
1939 mfxSize roiSize;
1940 roiSize.width = imagePrimarySurface.width;
1941 roiSize.height = imagePrimarySurface.height;
1942
1943 /* We need to fill up empty surface by background color...
1944 * iBackgroundColor is now U64, with 16 bits per channel (see mfx_vpp_hw.cpp)
1945 * it is easy for ARGB format as Initial background value ARGB*/
1946 if (imagePrimarySurface.format.fourcc == VA_FOURCC_ARGB)
1947 {
1948 uint32_t A, R, G, B;
1949 uint32_t iBackgroundColorRGBA;
1950
1951 A = (uint32_t)((pParams->iBackgroundColor >> 48) & 0x00ff);
1952 R = (uint32_t)((pParams->iBackgroundColor >> 32) & 0x00ff);
1953 G = (uint32_t)((pParams->iBackgroundColor >> 16) & 0x00ff);
1954 B = (uint32_t)((pParams->iBackgroundColor >> 0) & 0x00ff);
1955
1956 iBackgroundColorRGBA = (A << 24) | (R << 16) | (G << 8) | (B << 0);
1957
1958 bool setPlaneSts = SetPlaneROI<uint32_t>(iBackgroundColorRGBA, (uint32_t *)pPrimarySurfaceBuffer, imagePrimarySurface.pitches[0], roiSize);
1959 MFX_CHECK(setPlaneSts, MFX_ERR_DEVICE_FAILED);
1960 }
1961 /* A bit more complicated for NV12 as you need to do conversion ARGB => NV12 */
1962 if (imagePrimarySurface.format.fourcc == VA_FOURCC_NV12)
1963 {
1964 uint32_t Y = (uint32_t)((pParams->iBackgroundColor >> 32) & 0x00ff);
1965 uint32_t U = (uint32_t)((pParams->iBackgroundColor >> 16) & 0x00ff);
1966 uint32_t V = (uint32_t)((pParams->iBackgroundColor >> 0) & 0x00ff);
1967
1968 uint8_t valueY = (uint8_t) Y;
1969 int16_t valueUV = (int16_t)((V<<8) + U); // Keep in mind that short is stored in memory using little-endian notation
1970
1971 bool setPlaneSts = SetPlaneROI<uint8_t>(valueY, pPrimarySurfaceBuffer, imagePrimarySurface.pitches[0], roiSize);
1972 MFX_CHECK(setPlaneSts, MFX_ERR_DEVICE_FAILED);
1973
1974 // NV12 format -> need to divide height 2 times less
1975 roiSize.height = roiSize.height/2;
1976 // "UV" this is short (16 bit) value already
1977 // so need to divide width 2 times less too!
1978 roiSize.width = roiSize.width/2;
1979 setPlaneSts = SetPlaneROI<int16_t>(valueUV, (int16_t *)(pPrimarySurfaceBuffer + imagePrimarySurface.offsets[1]),
1980 imagePrimarySurface.pitches[1], roiSize);
1981 MFX_CHECK(setPlaneSts, MFX_ERR_DEVICE_FAILED);
1982 }
1983
1984 if (imagePrimarySurface.format.fourcc == VA_FOURCC_P010
1985 #if (MFX_VERSION >= 1031)
1986 || imagePrimarySurface.format.fourcc == VA_FOURCC_P016
1987 #endif
1988 )
1989 {
1990 uint32_t Y=0;
1991 uint32_t U=0;
1992 uint32_t V=0;
1993 if(imagePrimarySurface.format.fourcc == VA_FOURCC_P010 )
1994 {
1995 Y = (uint32_t)((pParams->iBackgroundColor >> 26) & 0xffC0);
1996 U = (uint32_t)((pParams->iBackgroundColor >> 10) & 0xffC0);
1997 V = (uint32_t)((pParams->iBackgroundColor << 6) & 0xffC0);
1998 }
1999 #if (MFX_VERSION >= 1031)
2000 else
2001 {
2002 // 12 bit depth is used for these CCs
2003 Y = (uint32_t)((pParams->iBackgroundColor >> 28) & 0xfff0);
2004 U = (uint32_t)((pParams->iBackgroundColor >> 12) & 0xfff0);
2005 V = (uint32_t)((pParams->iBackgroundColor << 4) & 0xfff0);
2006 }
2007 #endif
2008
2009 uint16_t valueY = (uint16_t)Y;
2010 uint32_t valueUV = (int32_t)((V << 16) + U); // Keep in mind that short is stored in memory using little-endian notation
2011
2012 bool setPlaneSts = SetPlaneROI<uint16_t>(valueY, (uint16_t*)pPrimarySurfaceBuffer, imagePrimarySurface.pitches[0], roiSize);
2013 MFX_CHECK(setPlaneSts, MFX_ERR_DEVICE_FAILED);
2014
2015 // NV12 format -> need to divide height 2 times less
2016 roiSize.height = roiSize.height / 2;
2017 // "UV" encodes 2 pixels in a row
2018 // so need to divide width 2 times
2019 roiSize.width = roiSize.width / 2;
2020 setPlaneSts = SetPlaneROI<uint32_t>(valueUV, (uint32_t *)(pPrimarySurfaceBuffer + imagePrimarySurface.offsets[1]),
2021 imagePrimarySurface.pitches[1], roiSize);
2022 MFX_CHECK(setPlaneSts, MFX_ERR_DEVICE_FAILED);
2023 }
2024
2025 vaSts = vaUnmapBuffer(m_vaDisplay, imagePrimarySurface.buf);
2026 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2027 vaSts = vaDestroyImage(m_vaDisplay, imagePrimarySurface.image_id);
2028 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2029 } // for ( int iPrSurfCount = 0; iPrSurfCount < 3; iPrSurfCount++)
2030 }
2031
2032 /* pParams->refCount is total number of processing surfaces:
2033 * in case of composition this is primary + sub streams*/
2034
2035 mfxU32 SampleCount = 1;
2036 mfxU32 refIdx = 0;
2037
2038 m_pipelineParam.resize(pParams->refCount + 1);
2039 m_pipelineParamID.resize(pParams->refCount + 1, VA_INVALID_ID);
2040 blend_state.resize(pParams->refCount + 1);
2041
2042 std::vector<VARectangle> input_region;
2043 input_region.resize(pParams->refCount + 1);
2044 std::vector<VARectangle> output_region;
2045 output_region.resize(pParams->refCount + 1);
2046 VASurfaceID *outputSurface = (VASurfaceID*)(pParams->targetSurface.hdl.first);
2047
2048 for( refIdx = 0; refIdx < SampleCount; refIdx++ )
2049 {
2050 mfxDrvSurface* pRefSurf = &(pParams->targetSurface);
2051 memset(&m_pipelineParam[refIdx], 0, sizeof(m_pipelineParam[refIdx]));
2052
2053 //VASurfaceID* srf_1 = (VASurfaceID*)(pRefSurf->hdl.first);
2054 //m_pipelineParam[refIdx].surface = *srf_1;
2055 /* First "primary" surface should be our allocated empty surface filled by background color.
2056 * Else we can not process first input surface as usual one */
2057 if (pParams->bBackgroundRequired)
2058 m_pipelineParam[refIdx].surface = m_primarySurface4Composition[0];
2059 //VASurfaceID *outputSurface = (VASurfaceID*)(pParams->targetSurface.hdl.first);
2060 //m_pipelineParam[refIdx].surface = *outputSurface;
2061
2062 // source cropping
2063 //mfxFrameInfo *inInfo = &(pRefSurf->frameInfo);
2064 mfxFrameInfo *outInfo = &(pParams->targetSurface.frameInfo);
2065 input_region[refIdx].y = 0;
2066 input_region[refIdx].x = 0;
2067 input_region[refIdx].height = outInfo->CropH;
2068 input_region[refIdx].width = outInfo->CropW;
2069 m_pipelineParam[refIdx].surface_region = &input_region[refIdx];
2070
2071 // destination cropping
2072 //mfxFrameInfo *outInfo = &(pParams->targetSurface.frameInfo);
2073 output_region[refIdx].y = 0; //outInfo->CropY;
2074 output_region[refIdx].x = 0; //outInfo->CropX;
2075 output_region[refIdx].height= outInfo->CropH;
2076 output_region[refIdx].width = outInfo->CropW;
2077 m_pipelineParam[refIdx].output_region = &output_region[refIdx];
2078
2079 /* Actually as background color managed by "m_primarySurface4Composition" surface
2080 * this param will not make sense */
2081 //m_pipelineParam[refIdx].output_background_color = pParams->iBackgroundColor;
2082
2083 mfxU32 refFourcc = pRefSurf->frameInfo.FourCC;
2084 switch (refFourcc)
2085 {
2086 case MFX_FOURCC_RGB4:
2087 m_pipelineParam[refIdx].surface_color_standard = VAProcColorStandardNone;
2088 break;
2089 case MFX_FOURCC_NV12:
2090 default:
2091 m_pipelineParam[refIdx].surface_color_standard = VAProcColorStandardBT601;
2092 break;
2093 }
2094
2095 mfxU32 targetFourcc = pParams->targetSurface.frameInfo.FourCC;
2096 switch (targetFourcc)
2097 {
2098 case MFX_FOURCC_RGB4:
2099 m_pipelineParam[refIdx].output_color_standard = VAProcColorStandardNone;
2100 break;
2101 case MFX_FOURCC_NV12:
2102 default:
2103 m_pipelineParam[refIdx].output_color_standard = VAProcColorStandardBT601;
2104 break;
2105 }
2106
2107 if(refIdx > 0 && pParams->VideoSignalInfo[refIdx-1].enabled)
2108 {
2109 if(pParams->VideoSignalInfo[refIdx-1].TransferMatrix != MFX_TRANSFERMATRIX_UNKNOWN)
2110 {
2111 m_pipelineParam[refIdx].surface_color_standard = (MFX_TRANSFERMATRIX_BT709 == pParams->VideoSignalInfo[refIdx-1].TransferMatrix) ? VAProcColorStandardBT709 : VAProcColorStandardBT601;
2112 }
2113
2114 if(pParams->VideoSignalInfo[refIdx-1].NominalRange != MFX_NOMINALRANGE_UNKNOWN)
2115 {
2116 m_pipelineParam[refIdx].input_color_properties.color_range = (MFX_NOMINALRANGE_0_255 == pParams->VideoSignalInfo[refIdx-1].NominalRange) ? VA_SOURCE_RANGE_FULL : VA_SOURCE_RANGE_REDUCED;
2117 }
2118 }
2119
2120 if (pParams->VideoSignalInfoOut.enabled)
2121 {
2122 if(pParams->VideoSignalInfoOut.TransferMatrix != MFX_TRANSFERMATRIX_UNKNOWN)
2123 {
2124 m_pipelineParam[refIdx].output_color_standard = (MFX_TRANSFERMATRIX_BT709 == pParams->VideoSignalInfoOut.TransferMatrix ? VAProcColorStandardBT709 : VAProcColorStandardBT601);
2125 }
2126
2127 if(pParams->VideoSignalInfoOut.NominalRange != MFX_NOMINALRANGE_UNKNOWN)
2128 {
2129 m_pipelineParam[refIdx].output_color_properties.color_range = (MFX_NOMINALRANGE_0_255 == pParams->VideoSignalInfoOut.NominalRange) ? VA_SOURCE_RANGE_FULL : VA_SOURCE_RANGE_REDUCED;
2130 }
2131 }
2132 m_pipelineParam[refIdx].input_color_properties.chroma_sample_location = VA_CHROMA_SITING_UNKNOWN;
2133 m_pipelineParam[refIdx].output_color_properties.chroma_sample_location = VA_CHROMA_SITING_UNKNOWN;
2134
2135 switch (pRefSurf->frameInfo.PicStruct)
2136 {
2137 case MFX_PICSTRUCT_PROGRESSIVE:
2138 default:
2139 m_pipelineParam[refIdx].filter_flags = VA_FRAME_PICTURE;
2140 break;
2141 }
2142
2143 m_pipelineParam[refIdx].filters = m_filterBufs;
2144 m_pipelineParam[refIdx].num_filters = m_numFilterBufs;
2145 /* Special case for composition:
2146 * as primary surface processed as sub-stream
2147 * pipeline and filter properties should be *_FAST */
2148 if (pParams->bComposite)
2149 {
2150 m_pipelineParam[refIdx].num_filters = 0;
2151
2152 if (m_pipelineCaps.pipeline_flags & VA_PROC_PIPELINE_FAST)
2153 m_pipelineParam[refIdx].pipeline_flags |= VA_PROC_PIPELINE_FAST;
2154 else
2155 m_pipelineParam[refIdx].pipeline_flags |= VA_PROC_PIPELINE_SUBPICTURES;
2156
2157 if (m_pipelineCaps.filter_flags & VA_FILTER_SCALING_HQ)
2158 m_pipelineParam[refIdx].filter_flags |= VA_FILTER_SCALING_HQ;
2159 }
2160 }
2161
2162 {
2163 MFX_LTRACE_2(MFX_TRACE_LEVEL_HOTSPOTS, "A|VPP|COMP|PACKET_START|", "%d|%d", m_vaContextVPP, 0);
2164 {
2165 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_SCHED, "vaBeginPicture");
2166 vaSts = vaBeginPicture(m_vaDisplay,
2167 m_vaContextVPP,
2168 *outputSurface);
2169 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2170 }
2171 }
2172
2173 if (pParams->bBackgroundRequired)
2174 {
2175 refIdx = 0;
2176 vaSts = vaCreateBuffer(m_vaDisplay,
2177 m_vaContextVPP,
2178 VAProcPipelineParameterBufferType,
2179 sizeof(VAProcPipelineParameterBuffer),
2180 1,
2181 &m_pipelineParam[refIdx],
2182 &m_pipelineParamID[refIdx]);
2183 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2184
2185 {
2186 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_SCHED, "vaRenderPicture");
2187 for( refIdx = 0; refIdx < SampleCount; refIdx++ )
2188 {
2189 vaSts = vaRenderPicture(m_vaDisplay, m_vaContextVPP, &m_pipelineParamID[refIdx], 1);
2190 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2191 }
2192 }
2193 } // if (pParams->bBackgroundRequired)
2194
2195 unsigned int uBeginPictureCounter = 0;
2196 std::vector<VAProcPipelineParameterBuffer> m_pipelineParamComp;
2197 std::vector<VABufferID> m_pipelineParamCompID;
2198 /* for new buffers for Begin Picture*/
2199 m_pipelineParamComp.resize(pParams->fwdRefCount/7);
2200 m_pipelineParamCompID.resize(pParams->fwdRefCount/7, VA_INVALID_ID);
2201
2202 /* pParams->fwdRefCount actually is number of sub stream*/
2203 for( refIdx = 1; refIdx <= (refCount + 1); refIdx++ )
2204 {
2205 /*for frames 8, 15, 22, 29,... */
2206 if ((refIdx != 1) && ((refIdx %7) == 1) )
2207 {
2208 {
2209 vaSts = vaBeginPicture(m_vaDisplay,
2210 m_vaContextVPP,
2211 *outputSurface);
2212 }
2213 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2214 /*to copy initial properties of primary surface... */
2215 m_pipelineParamComp[uBeginPictureCounter] = m_pipelineParam[0];
2216 /* ... and to In-place output*/
2217 //m_pipelineParamComp[uBeginPictureCounter].surface = m_primarySurface4Composition[uInputIndex];
2218 m_pipelineParamComp[uBeginPictureCounter].surface = *outputSurface;
2219 //m_pipelineParam[0].surface = *outputSurface;
2220 /* As used IN-PLACE variant of Composition
2221 * this values does not used*/
2222 //uOutputIndex++;
2223 //uInputIndex++;
2224 //if (uOutputIndex > 2)
2225 // uOutputIndex = 0;
2226 //if (uInputIndex > 2)
2227 // uInputIndex = 0;
2228
2229 switch (pParams->targetSurface.frameInfo.FourCC)
2230 {
2231 case MFX_FOURCC_RGB4:
2232 m_pipelineParamComp[uBeginPictureCounter].surface_color_standard = VAProcColorStandardNone;
2233 break;
2234 case MFX_FOURCC_NV12:
2235 default:
2236 m_pipelineParamComp[uBeginPictureCounter].surface_color_standard = (MFX_TRANSFERMATRIX_BT709 == pParams->VideoSignalInfoOut.TransferMatrix) ? VAProcColorStandardBT709 : VAProcColorStandardBT601;
2237 break;
2238 }
2239
2240 vaSts = vaCreateBuffer(m_vaDisplay,
2241 m_vaContextVPP,
2242 VAProcPipelineParameterBufferType,
2243 sizeof(VAProcPipelineParameterBuffer),
2244 1,
2245 &m_pipelineParamComp[uBeginPictureCounter],
2246 &m_pipelineParamCompID[uBeginPictureCounter]);
2247 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2248
2249 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_SCHED, "vaBeginPicture");
2250 vaSts = vaRenderPicture(m_vaDisplay, m_vaContextVPP, &m_pipelineParamCompID[uBeginPictureCounter], 1);
2251 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2252
2253 uBeginPictureCounter++;
2254 }
2255
2256 m_pipelineParam[refIdx] = m_pipelineParam[0];
2257
2258 mfxDrvSurface* pRefSurf = &(pParams->pRefSurfaces[refIdx-1]);
2259
2260 VASurfaceID* srf_2 = (VASurfaceID*)(pRefSurf->hdl.first);
2261
2262 m_pipelineParam[refIdx].surface = *srf_2;
2263
2264 mfxU32 refFourcc = pRefSurf->frameInfo.FourCC;
2265 switch (refFourcc)
2266 {
2267 case MFX_FOURCC_RGB4:
2268 m_pipelineParam[refIdx].surface_color_standard = VAProcColorStandardNone;
2269 break;
2270 case MFX_FOURCC_NV12:
2271 default:
2272 m_pipelineParam[refIdx].surface_color_standard = VAProcColorStandardBT601;
2273 break;
2274 }
2275
2276 if(refIdx > 0 && pParams->VideoSignalInfo[refIdx-1].enabled)
2277 {
2278 if(pParams->VideoSignalInfo[refIdx-1].TransferMatrix != MFX_TRANSFERMATRIX_UNKNOWN)
2279 {
2280 m_pipelineParam[refIdx].surface_color_standard = (MFX_TRANSFERMATRIX_BT709 == pParams->VideoSignalInfo[refIdx-1].TransferMatrix ? VAProcColorStandardBT709 : VAProcColorStandardBT601);
2281 }
2282
2283 if(pParams->VideoSignalInfo[refIdx-1].NominalRange != MFX_NOMINALRANGE_UNKNOWN)
2284 {
2285 m_pipelineParam[refIdx].input_color_properties.color_range = (MFX_NOMINALRANGE_0_255 == pParams->VideoSignalInfo[refIdx-1].NominalRange) ? VA_SOURCE_RANGE_FULL : VA_SOURCE_RANGE_REDUCED;
2286 }
2287 }
2288
2289 if (pParams->VideoSignalInfoOut.enabled)
2290 {
2291 if(pParams->VideoSignalInfoOut.TransferMatrix != MFX_TRANSFERMATRIX_UNKNOWN)
2292 {
2293 m_pipelineParam[refIdx].output_color_standard = (MFX_TRANSFERMATRIX_BT709 == pParams->VideoSignalInfoOut.TransferMatrix ? VAProcColorStandardBT709 : VAProcColorStandardBT601);
2294 }
2295
2296 if(pParams->VideoSignalInfoOut.NominalRange != MFX_NOMINALRANGE_UNKNOWN)
2297 {
2298 m_pipelineParam[refIdx].output_color_properties.color_range = (MFX_NOMINALRANGE_0_255 == pParams->VideoSignalInfoOut.NominalRange) ? VA_SOURCE_RANGE_FULL : VA_SOURCE_RANGE_REDUCED;
2299 }
2300 }
2301 m_pipelineParam[refIdx].input_color_properties.chroma_sample_location = VA_CHROMA_SITING_UNKNOWN;
2302 m_pipelineParam[refIdx].output_color_properties.chroma_sample_location = VA_CHROMA_SITING_UNKNOWN;
2303
2304 /* to process input parameters of sub stream:
2305 * crop info and original size*/
2306 mfxFrameInfo *inInfo = &(pRefSurf->frameInfo);
2307 input_region[refIdx].y = inInfo->CropY;
2308 input_region[refIdx].x = inInfo->CropX;
2309 input_region[refIdx].height = inInfo->CropH;
2310 input_region[refIdx].width = inInfo->CropW;
2311 m_pipelineParam[refIdx].surface_region = &input_region[refIdx];
2312
2313 /* to process output parameters of sub stream:
2314 * position and destination size */
2315 output_region[refIdx].y = pParams->dstRects[refIdx-1].DstY;
2316 output_region[refIdx].x = pParams->dstRects[refIdx-1].DstX;
2317 output_region[refIdx].height= pParams->dstRects[refIdx-1].DstH;
2318 output_region[refIdx].width = pParams->dstRects[refIdx-1].DstW;
2319 m_pipelineParam[refIdx].output_region = &output_region[refIdx];
2320
2321 /* Global alpha and luma key can not be enabled together*/
2322 /* Global alpha and luma key can not be enabled together*/
2323 if (pParams->dstRects[refIdx-1].GlobalAlphaEnable !=0)
2324 {
2325 blend_state[refIdx].flags = VA_BLEND_GLOBAL_ALPHA;
2326 blend_state[refIdx].global_alpha = ((float)pParams->dstRects[refIdx-1].GlobalAlpha) /255;
2327 }
2328 /* Luma color key for YUV surfaces only.
2329 * And Premultiplied alpha blending for RGBA surfaces only.
2330 * So, these two flags can't combine together */
2331 if ((pParams->dstRects[refIdx-1].LumaKeyEnable != 0) &&
2332 (pParams->dstRects[refIdx-1].PixelAlphaEnable == 0) )
2333 {
2334 blend_state[refIdx].flags |= VA_BLEND_LUMA_KEY;
2335 blend_state[refIdx].min_luma = ((float)pParams->dstRects[refIdx-1].LumaKeyMin/255);
2336 blend_state[refIdx].max_luma = ((float)pParams->dstRects[refIdx-1].LumaKeyMax/255);
2337 }
2338 if ((pParams->dstRects[refIdx-1].LumaKeyEnable == 0 ) &&
2339 (pParams->dstRects[refIdx-1].PixelAlphaEnable != 0 ) )
2340 {
2341 /* Per-pixel alpha case. Having VA_BLEND_PREMULTIPLIED_ALPHA as a parameter
2342 * leads to using BLEND_PARTIAL approach by driver that may produce
2343 * "white line"-like artifacts on transparent-opaque borders.
2344 * Setting nothing here triggers using a BLEND_SOURCE approach that is used on
2345 * Windows and looks to be free of such kind of artifacts */
2346 blend_state[refIdx].flags |= 0;
2347 }
2348 if ((pParams->dstRects[refIdx-1].GlobalAlphaEnable != 0) ||
2349 (pParams->dstRects[refIdx-1].LumaKeyEnable != 0) ||
2350 (pParams->dstRects[refIdx-1].PixelAlphaEnable != 0))
2351 {
2352 m_pipelineParam[refIdx].blend_state = &blend_state[refIdx];
2353 }
2354
2355 //m_pipelineParam[refIdx].pipeline_flags = ?? //VA_PROC_PIPELINE_FAST or VA_PROC_PIPELINE_SUBPICTURES
2356 m_pipelineParam[refIdx].pipeline_flags |= VA_PROC_PIPELINE_FAST;
2357 m_pipelineParam[refIdx].filter_flags |= VA_FILTER_SCALING_FAST;
2358
2359 m_pipelineParam[refIdx].filters = m_filterBufs;
2360 m_pipelineParam[refIdx].num_filters = 0;
2361
2362 vaSts = vaCreateBuffer(m_vaDisplay,
2363 m_vaContextVPP,
2364 VAProcPipelineParameterBufferType,
2365 sizeof(VAProcPipelineParameterBuffer),
2366 1,
2367 &m_pipelineParam[refIdx],
2368 &m_pipelineParamID[refIdx]);
2369 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2370
2371 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_SCHED, "vaRenderPicture");
2372 vaSts = vaRenderPicture(m_vaDisplay, m_vaContextVPP, &m_pipelineParamID[refIdx], 1);
2373 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2374
2375 /*for frames 7, 14, 21, ...
2376 * or for the last frame*/
2377 if ( ((refIdx % 7) ==0) || ((refCount + 1) == refIdx) )
2378 {
2379 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_SCHED, "vaEndPicture");
2380 vaSts = vaEndPicture(m_vaDisplay, m_vaContextVPP);
2381 MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2382 }
2383 } /* for( refIdx = 1; refIdx <= (pParams->fwdRefCount); refIdx++ )*/
2384 MFX_LTRACE_2(MFX_TRACE_LEVEL_HOTSPOTS, "A|VPP|COMP|PACKET_END|", "%d|%d", m_vaContextVPP, 0);
2385
2386 mfxStatus sts;
2387 for (VABufferID& id : m_pipelineParamCompID)
2388 {
2389 sts = CheckAndDestroyVAbuffer(m_vaDisplay, id);
2390 MFX_CHECK_STS(sts);
2391 }
2392
2393 for (VABufferID& id : m_pipelineParamID)
2394 {
2395 sts = CheckAndDestroyVAbuffer(m_vaDisplay, id);
2396 MFX_CHECK_STS(sts);
2397 }
2398
2399 // (3) info needed for sync operation
2400 //-------------------------------------------------------
2401 {
2402 UMC::AutomaticUMCMutex guard(m_guard);
2403
2404 ExtVASurface currentFeedback; // {surface & number_of_task}
2405 currentFeedback.surface = *outputSurface;
2406 currentFeedback.number = pParams->statusReportID;
2407 m_feedbackCache.push_back(currentFeedback);
2408 }
2409
2410 return MFX_ERR_NONE;
2411 } // mfxStatus VAAPIVideoProcessing::Execute_Composition(mfxExecuteParams *pParams)
2412 #else
Execute_Composition_TiledVideoWall(mfxExecuteParams * pParams)2413 mfxStatus VAAPIVideoProcessing::Execute_Composition_TiledVideoWall(mfxExecuteParams *pParams)
2414 {
2415 return MFX_ERR_UNSUPPORTED;
2416 }
2417
Execute_Composition(mfxExecuteParams * pParams)2418 mfxStatus VAAPIVideoProcessing::Execute_Composition(mfxExecuteParams *pParams)
2419 {
2420 return MFX_ERR_UNSUPPORTED;
2421 }
2422 #endif //#ifdef MFX_ENABLE_VPP_COMPOSITION
2423
QueryTaskStatus(mfxU32 taskIndex)2424 mfxStatus VAAPIVideoProcessing::QueryTaskStatus(mfxU32 taskIndex)
2425 {
2426 VASurfaceID waitSurface = VA_INVALID_SURFACE;
2427 mfxU32 indxSurf = 0;
2428
2429 // (1) find params (sutface & number) are required by feedbackNumber
2430 //-----------------------------------------------
2431 {
2432 UMC::AutomaticUMCMutex guard(m_guard);
2433
2434 for (indxSurf = 0; indxSurf < m_feedbackCache.size(); indxSurf++)
2435 {
2436 if (m_feedbackCache[indxSurf].number == taskIndex)
2437 {
2438 waitSurface = m_feedbackCache[indxSurf].surface;
2439 break;
2440 }
2441 }
2442 if (VA_INVALID_SURFACE == waitSurface)
2443 {
2444 return MFX_ERR_UNKNOWN;
2445 }
2446
2447 m_feedbackCache.erase(m_feedbackCache.begin() + indxSurf);
2448 }
2449
2450 #if !defined(ANDROID)
2451 {
2452 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaSyncSurface");
2453 VAStatus vaSts = vaSyncSurface(m_vaDisplay, waitSurface);
2454 if (vaSts == VA_STATUS_ERROR_HW_BUSY)
2455 return MFX_ERR_GPU_HANG;
2456 else
2457 MFX_CHECK(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
2458 }
2459 #endif
2460
2461 return MFX_TASK_DONE;
2462 } // mfxStatus VAAPIVideoProcessing::QueryTaskStatus(mfxU32 taskIndex)
2463
2464 #endif // #if defined (MFX_VA_LINUX)
2465 #endif // #if defined (MFX_VPP_ENABLE)
2466 /* EOF */
2467