1 // Copyright (c) 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 "mctf_common.h"
22 #include "asc.h"
23 #include "asc_defs.h"
24 
25 #include "genx_me_gen8_isa.h"
26 #include "genx_mc_gen8_isa.h"
27 #include "genx_sd_gen8_isa.h"
28 
29 #include "genx_me_gen9_isa.h"
30 #include "genx_mc_gen9_isa.h"
31 #include "genx_sd_gen9_isa.h"
32 
33 #include "genx_me_gen11_isa.h"
34 #include "genx_mc_gen11_isa.h"
35 #include "genx_sd_gen11_isa.h"
36 
37 #include "genx_me_gen11lp_isa.h"
38 #include "genx_mc_gen11lp_isa.h"
39 #include "genx_sd_gen11lp_isa.h"
40 #include "genx_me_gen12lp_isa.h"
41 #include "genx_mc_gen12lp_isa.h"
42 #include "genx_sd_gen12lp_isa.h"
43 
44 #include <algorithm>
45 #include <climits>
46 #include <cmath>
47 #include <limits>
48 #include "cmrt_cross_platform.h"
49 
50 using std::min;
51 using  std::max;
52 using namespace ns_asc;
53 
54 const mfxU16 CMC::AUTO_FILTER_STRENGTH    = 0;
55 const mfxU16 CMC::DEFAULT_FILTER_STRENGTH = 8;
56 const mfxU16 CMC::INPIPE_FILTER_STRENGTH  = 5;
57 const mfxU32 CMC::DEFAULT_BPP             = 0; //Automode
58 const mfxU16 CMC::DEFAULT_DEBLOCKING      = MFX_CODINGOPTION_OFF;
59 const mfxU16 CMC::DEFAULT_OVERLAP         = MFX_CODINGOPTION_OFF;
60 const mfxU16 CMC::DEFAULT_ME              = MFX_MVPRECISION_INTEGER >> 1;
61 const mfxU16 CMC::DEFAULT_REFS            = MCTF_TEMPORAL_MODE_2REF;
62 
QueryDefaultParams(IntMctfParams * pBuffer)63 void CMC::QueryDefaultParams(
64     IntMctfParams * pBuffer
65 )
66 {
67     if (!pBuffer) return;
68     pBuffer->Deblocking        = DEFAULT_DEBLOCKING;
69     pBuffer->Overlap           = DEFAULT_OVERLAP;
70     pBuffer->subPelPrecision   = DEFAULT_ME;
71     pBuffer->TemporalMode      = DEFAULT_REFS;
72     pBuffer->FilterStrength    = DEFAULT_FILTER_STRENGTH; // [0...20]
73     pBuffer->BitsPerPixelx100k = DEFAULT_BPP;
74 };
75 
QueryDefaultParams(mfxExtVppMctf * pBuffer)76 void CMC::QueryDefaultParams(
77     mfxExtVppMctf * pBuffer
78 )
79 {
80     if (!pBuffer) return;
81     IntMctfParams
82         Mctfparam;
83     QueryDefaultParams(&Mctfparam);
84     pBuffer->FilterStrength     = Mctfparam.FilterStrength;
85 #ifdef MFX_ENABLE_MCTF_EXT
86     pBuffer->BitsPerPixelx100k  = Mctfparam.BitsPerPixelx100k;
87     pBuffer->Overlap            = Mctfparam.Overlap;
88     pBuffer->Deblocking         = Mctfparam.Deblocking;
89     pBuffer->TemporalMode       = Mctfparam.TemporalMode;
90     pBuffer->MVPrecision        = Mctfparam.subPelPrecision;
91 #endif
92 };
93 
CheckAndFixParams(mfxExtVppMctf * pBuffer)94 mfxStatus CMC::CheckAndFixParams(
95     mfxExtVppMctf * pBuffer
96 )
97 {
98     mfxStatus
99         sts = MFX_ERR_NONE;
100     if (!pBuffer) return MFX_ERR_NULL_PTR;
101     if (pBuffer->FilterStrength > 20)
102     {
103         pBuffer->FilterStrength = AUTO_FILTER_STRENGTH;
104         sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
105     }
106 #ifdef MFX_ENABLE_MCTF_EXT
107     if (MFX_CODINGOPTION_OFF != pBuffer->Deblocking &&
108         MFX_CODINGOPTION_ON != pBuffer->Deblocking &&
109         MFX_CODINGOPTION_UNKNOWN != pBuffer->Deblocking) {
110         pBuffer->Deblocking = DEFAULT_DEBLOCKING;
111         sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
112     }else
113         if (MFX_CODINGOPTION_UNKNOWN == pBuffer->Deblocking){
114             pBuffer->Deblocking = DEFAULT_DEBLOCKING;
115             // keep previous status to not override possibe WRN
116         }
117     if (MFX_CODINGOPTION_OFF != pBuffer->Overlap &&
118         MFX_CODINGOPTION_ON != pBuffer->Overlap &&
119         MFX_CODINGOPTION_UNKNOWN != pBuffer->Overlap) {
120         pBuffer->Overlap = DEFAULT_OVERLAP;
121         sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
122     }else
123         if (MFX_CODINGOPTION_UNKNOWN == pBuffer->Overlap) {
124             pBuffer->Overlap = DEFAULT_OVERLAP;
125             // keep previous status to not override possibe WRN
126         }
127 
128     if (MCTF_TEMPORAL_MODE_SPATIAL != pBuffer->TemporalMode &&
129         MCTF_TEMPORAL_MODE_1REF != pBuffer->TemporalMode &&
130         MCTF_TEMPORAL_MODE_2REF != pBuffer->TemporalMode &&
131         MCTF_TEMPORAL_MODE_4REF != pBuffer->TemporalMode &&
132         MCTF_TEMPORAL_MODE_UNKNOWN != pBuffer->TemporalMode) {
133         pBuffer->TemporalMode = DEFAULT_REFS;
134         sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
135     }else
136         if (MCTF_TEMPORAL_MODE_UNKNOWN == pBuffer->TemporalMode) {
137             pBuffer->TemporalMode = DEFAULT_REFS;
138             // keep previous status to not override possibe WRN
139         }
140 
141 
142     if (MFX_MVPRECISION_INTEGER != pBuffer->MVPrecision &&
143         MFX_MVPRECISION_QUARTERPEL != pBuffer->MVPrecision &&
144         MFX_MVPRECISION_UNKNOWN != pBuffer->MVPrecision) {
145         pBuffer->MVPrecision = DEFAULT_ME;
146         sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
147     }else
148         if (MFX_MVPRECISION_UNKNOWN == pBuffer->MVPrecision)
149         {
150             pBuffer->MVPrecision = DEFAULT_ME;
151             // keep previous status to not override possibe WRN
152         }
153 
154     if (pBuffer->BitsPerPixelx100k > DEFAULT_BPP) {
155         pBuffer->BitsPerPixelx100k = DEFAULT_BPP;
156         sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
157     }
158 #endif
159     return sts;
160 }
161 
162 // this function fills MCTF params based on extended buffer
FillParamControl(IntMctfParams * pBuffer,const mfxExtVppMctf * pSrc)163 void CMC::FillParamControl(
164     IntMctfParams       * pBuffer,
165     const mfxExtVppMctf * pSrc
166 )
167 {
168     pBuffer->FilterStrength     = pSrc->FilterStrength;
169 #ifdef MFX_ENABLE_MCTF_EXT
170     pBuffer->Deblocking         = pSrc->Deblocking;
171     pBuffer->Overlap            = pSrc->Overlap;
172     pBuffer->subPelPrecision    = pSrc->MVPrecision;
173     pBuffer->TemporalMode       = pSrc->TemporalMode;
174     pBuffer->BitsPerPixelx100k  = pSrc->BitsPerPixelx100k;
175 #endif
176 }
177 
SetFilterStrenght(unsigned short tFs,unsigned short sFs)178 mfxStatus CMC::SetFilterStrenght(
179     unsigned short tFs,//Temporal filter strength
180     unsigned short sFs //Spatial filter strength
181 )
182 {
183     if (tFs > 21 || sFs > 21)
184         return MFX_ERR_INVALID_VIDEO_PARAM;
185 
186     p_ctrl->th  = tFs * 50;
187     if (sFs)
188         p_ctrl->sTh = (mfxU16)min(sFs + CHROMABASE, MAXCHROMA);
189     else
190         p_ctrl->sTh = MCTFNOFILTER;
191     res         = ctrlBuf->WriteSurface((const uint8_t *)p_ctrl.get(), NULL, sizeof(MeControlSmall));
192     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
193     return MFX_ERR_NONE;
194 }
195 
SetFilterStrenght(unsigned short fs)196 inline mfxStatus CMC::SetFilterStrenght(
197     unsigned short fs
198 )
199 {
200     MCTF_CHECK_CM_ERR(SetFilterStrenght(fs, fs), MFX_ERR_DEVICE_FAILED);
201     return MFX_ERR_NONE;
202 }
203 
SetupMeControl(const mfxFrameInfo & FrameInfo,mfxU16 th,mfxU16 subPelPre)204 inline mfxStatus CMC::SetupMeControl(
205     const mfxFrameInfo & FrameInfo,
206     mfxU16               th,
207     mfxU16               subPelPre
208 )
209 {
210     p_ctrl.reset(new MeControlSmall);
211     const mfxU8 Diamond[MCTFSEARCHPATHSIZE] = {
212         0x0F,0xF1,0x0F,0x12,//5
213         0x0D,0xE2,0x22,0x1E,//9
214         0x10,0xFF,0xE2,0x20,//13
215         0xFC,0x06,0xDD,//16
216         0x2E,0xF1,0x3F,0xD3,0x11,0x3D,0xF3,0x1F,//24
217         0xEB,0xF1,0xF1,0xF1,//28
218         0x4E,0x11,0x12,0xF2,0xF1,//33
219         0xE0,0xFF,0xFF,0x0D,0x1F,0x1F,//39
220         0x20,0x11,0xCF,0xF1,0x05,0x11,//45
221         0x00,0x00,0x00,0x00,0x00,0x00,//51
222     };
223     std::copy(std::begin(Diamond), std::end(Diamond), std::begin(p_ctrl->searchPath.sp));
224 
225     p_ctrl->searchPath.lenSp    = 16;
226     p_ctrl->searchPath.maxNumSu = 57;
227 
228     p_ctrl->width  = FrameInfo.Width;
229     p_ctrl->height = FrameInfo.Height;
230 
231     mfxU16 CropX(FrameInfo.CropX), CropY(FrameInfo.CropY), CropW(FrameInfo.CropW), CropH(FrameInfo.CropH);
232 
233     // this code align crop regin to CROP_BLOCK_ALIGNMENT boundary;
234     // doing this, it follows the principle that initial crop-region
235     // to be included in the crop-region after alignment;
236 
237     mfxU16 CropRBX = CropX + CropW - 1;
238     mfxU16 CropRBY = CropY + CropH - 1;
239     CropX = (CropX / CROP_BLOCK_ALIGNMENT) * CROP_BLOCK_ALIGNMENT;
240     CropY = (CropY / CROP_BLOCK_ALIGNMENT) * CROP_BLOCK_ALIGNMENT;
241     CropW = CropRBX - CropX + 1;
242     CropH = CropRBY - CropY + 1;
243 
244     CropW = (DIVUP(CropW, CROP_BLOCK_ALIGNMENT)) * CROP_BLOCK_ALIGNMENT;
245     CropH = (DIVUP(CropH, CROP_BLOCK_ALIGNMENT)) * CROP_BLOCK_ALIGNMENT;
246 
247     if ((CropX + CropW > FrameInfo.Width) || (CropY + CropH > FrameInfo.Height))
248         return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
249 
250     p_ctrl->CropX = CropX;
251     p_ctrl->CropY = CropY;
252     p_ctrl->CropW = CropW;
253     p_ctrl->CropH = CropH;
254 
255     if (th > 20)
256         return MFX_ERR_INVALID_VIDEO_PARAM;
257     p_ctrl->th  = th * 50;
258     p_ctrl->sTh = (mfxU16)min(th + CHROMABASE, MAXCHROMA);
259     p_ctrl->mre_width  = 0;
260     p_ctrl->mre_height = 0;
261     if (MFX_MVPRECISION_INTEGER >> 1 == subPelPre)
262         p_ctrl->subPrecision = 0;
263     else
264         if (MFX_MVPRECISION_QUARTERPEL >> 1 == subPelPre)
265             p_ctrl->subPrecision = 1;
266         else
267             return MFX_ERR_INVALID_VIDEO_PARAM;
268     return MFX_ERR_NONE;
269 }
270 
MCTF_GET_FRAME(CmSurface2D * outFrame)271 mfxStatus CMC::MCTF_GET_FRAME(
272     CmSurface2D * outFrame
273 )
274 {
275     mfxStatus sts = MFX_ERR_NONE;
276     if (!outFrame)
277         return MFX_ERR_UNDEFINED_BEHAVIOR;
278     if (!mco)
279     {
280         // we are in the end of a stream, and it must be the configuration with
281         // > 1 reference as there is no reason to get another surface out of MCTF
282         // if no delay was assumed.
283         if (NO_REFERENCES == number_of_References || ONE_REFERENCE == number_of_References)
284         {
285             //this is undefined behavior
286             return MFX_ERR_UNDEFINED_BEHAVIOR;
287         }
288         else
289         {
290             // let map outframe to mco
291             mco = outFrame;
292             INT cmSts = mco->GetIndex(idxMco);
293             MFX_CHECK((CM_SUCCESS == cmSts), MFX_ERR_DEVICE_FAILED);
294         }
295     }
296 
297     if (QfIn.size() == 5)
298     {
299         if (lastFrame == 1)
300         {
301             res = MCTF_RUN_MCTF_DEN(true);
302             lastFrame++;
303         }
304         else if (lastFrame == 2)
305             MCTF_RUN_AMCTF(lastFrame);
306     }
307     else if (QfIn.size() == 3)
308     {
309         if (lastFrame == 1)
310             //res = MCTF_RUN_AMCTF(lastFrame);
311             res = MCTF_RUN_MCTF_DEN(true);
312     }
313 
314     MFX_CHECK(mco, MFX_ERR_UNDEFINED_BEHAVIOR);
315     mco = nullptr;
316     if (!lastFrame)
317         lastFrame = 1;
318     return sts;
319 }
320 
MCTF_GET_FRAME(mfxU8 * outFrame)321 mfxStatus CMC::MCTF_GET_FRAME(
322     mfxU8 * outFrame
323 )
324 {
325     mfxStatus sts = MFX_ERR_NONE;
326     if (!outFrame)
327         return MFX_ERR_UNDEFINED_BEHAVIOR;
328     if (!mco)
329     {
330         if (NO_REFERENCES == number_of_References || ONE_REFERENCE == number_of_References)
331         {
332             //this is undefined behavior
333             return MFX_ERR_UNDEFINED_BEHAVIOR;
334         }
335         else
336             return MFX_ERR_DEVICE_FAILED;
337     }
338 
339     if (lastFrame == 1)
340         res = MCTF_RUN_MCTF_DEN(true);
341 
342     MFX_CHECK(mco, MFX_ERR_UNDEFINED_BEHAVIOR);
343 
344     if (QfIn[0].filterStrength > 0)
345     {
346         res = queue->EnqueueCopyGPUToCPU(mco, outFrame, copyEv);
347         MFX_CHECK((CM_SUCCESS == res), MFX_ERR_DEVICE_FAILED);
348 
349         CM_STATUS
350             status = CM_STATUS_FLUSHED;
351 
352         copyEv->GetStatus(status);
353         while (status != CM_STATUS_FINISHED)
354             copyEv->GetStatus(status);
355 
356         MctfState = AMCTF_NOT_READY;
357     }
358 
359     return sts;
360 }
361 
MCTF_CHECK_FILTER_USE()362 bool CMC::MCTF_CHECK_FILTER_USE()
363 {
364     if (QfIn.front().filterStrength == 0)
365         return false;
366     return true;
367 }
368 
MCTF_RELEASE_FRAME(bool isCmUsed)369 mfxStatus CMC::MCTF_RELEASE_FRAME(
370     bool isCmUsed
371 )
372 {
373     if (MCTF_ReadyToOutput())
374     {
375         MctfState = AMCTF_NOT_READY;
376         if (mco2)
377         {
378             mco = mco2;
379             idxMco = idxMco2;
380             mco2 = nullptr;
381             idxMco2 = nullptr;
382         }
383     }
384     //Buffer has rotated enough at this point that last position is old and needs to eb recycled.
385     if (isCmUsed)
386     {
387         if (QfIn.back().frameData)
388         {
389             device->DestroySurface(QfIn.back().frameData);//This Surface is created by MCTF and needs to be destroyed after denoised frame has been used.
390             QfIn.back().frameData = nullptr;
391             QfIn.back().fIdx      = nullptr;
392             QfIn.back().mfxFrame  = nullptr;
393         }
394     }
395     return MFX_ERR_NONE;
396 }
397 
MCTF_TrackTimeStamp(mfxFrameSurface1 * outFrame)398 mfxStatus CMC::MCTF_TrackTimeStamp(
399     mfxFrameSurface1 * outFrame
400 )
401 {
402     outFrame->Data.FrameOrder = QfIn[CurrentIdx2Out].mfxFrame->Data.FrameOrder;
403     outFrame->Data.TimeStamp = QfIn[CurrentIdx2Out].mfxFrame->Data.TimeStamp;
404     return MFX_ERR_NONE;
405 }
406 
MCTF_InitQueue(mfxU16 refNum)407 mfxStatus CMC::MCTF_InitQueue(
408     mfxU16 refNum
409 )
410 {
411     mfxU32  buffer_size(0);
412     switch (refNum)
413     {
414     case MCTF_TEMPORAL_MODE_4REF:
415     {
416         number_of_References = FOUR_REFERENCES;
417         DefaultIdx2Out = 1;
418         CurrentIdx2Out = 0;
419         MctfState = AMCTF_NOT_READY;
420         buffer_size = FOUR_REFERENCES + 1;
421     };
422     break;
423     case MCTF_TEMPORAL_MODE_2REF:
424     {
425         number_of_References = TWO_REFERENCES;
426         DefaultIdx2Out = 0;
427         CurrentIdx2Out = 0;
428         MctfState = AMCTF_NOT_READY;
429         buffer_size = TWO_REFERENCES + 1;
430     };
431     break;
432     case MCTF_TEMPORAL_MODE_1REF:
433     {
434         number_of_References = ONE_REFERENCE;
435         DefaultIdx2Out = 0;
436         CurrentIdx2Out = 0;
437         MctfState = AMCTF_READY;
438         buffer_size = ONE_REFERENCE + 1;
439     };
440     break;
441     case MCTF_TEMPORAL_MODE_SPATIAL:
442     { //refNum == 0
443         number_of_References = NO_REFERENCES;
444         DefaultIdx2Out = 0;
445         CurrentIdx2Out = 0;
446         MctfState = AMCTF_READY;
447         buffer_size = ONE_REFERENCE ;
448     };
449     break;
450     default:
451         return MFX_ERR_INVALID_VIDEO_PARAM;
452     };
453 
454     for (mfxU8 i = 0; i < buffer_size; i++)
455     {
456         scene_numbers[i] = 0;
457         QfIn.push_back(gpuFrameData());
458     }
459 
460     return MFX_ERR_NONE;
461 }
462 
DIM_SET(mfxU16 overlap)463 mfxStatus CMC::DIM_SET(
464     mfxU16 overlap
465 )
466 {
467 //    if (p_ctrl->height <= MINHEIGHT)
468     if (p_ctrl->CropH <= MINHEIGHT)
469         blsize = 8;
470     if (MFX_CODINGOPTION_OFF != overlap &&
471         MFX_CODINGOPTION_ON != overlap &&
472         MFX_CODINGOPTION_UNKNOWN != overlap)
473         return MFX_ERR_INVALID_VIDEO_PARAM;
474     overlap_Motion = overlap;
475     switch (overlap_Motion)
476     {
477     case MFX_CODINGOPTION_ON:
478     {
479         ov_width_bl = (DIVUP(p_ctrl->CropW, blsize) * 2) - 1;
480         ov_height_bl = (DIVUP(p_ctrl->CropH, blsize) * 2) - 1;
481     }
482     break;
483     case MFX_CODINGOPTION_UNKNOWN:
484     case MFX_CODINGOPTION_OFF:
485     {
486         ov_width_bl = DIVUP(p_ctrl->CropW, blsize) * 2;
487         ov_height_bl = DIVUP(p_ctrl->CropH, blsize) * 2;
488     }
489     break;
490     default:
491         return MFX_ERR_INVALID_VIDEO_PARAM;
492     }
493     int var_sc_area = DIVUP(p_ctrl->CropW, 16) * DIVUP(p_ctrl->CropH, 16);
494     distRef.resize(ov_width_bl * ov_height_bl, 0);
495     var_sc.resize(var_sc_area);
496 
497     return MFX_ERR_NONE;
498 }
499 
500 
IM_SURF_SET(CmSurface2D ** p_surface,SurfaceIndex ** p_idxSurf)501 mfxStatus CMC::IM_SURF_SET(
502     CmSurface2D  ** p_surface,
503     SurfaceIndex ** p_idxSurf
504 )
505 {
506     res = device->CreateSurface2D(p_ctrl->width, p_ctrl->height, CM_SURFACE_FORMAT_NV12, *p_surface);
507     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
508     res = (*p_surface)->GetIndex(*p_idxSurf);
509     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
510     return MFX_ERR_NONE;
511 }
512 
IM_SURF_SET(AbstractSurfaceHandle pD3DSurf,CmSurface2D ** p_surface,SurfaceIndex ** p_idxSurf)513 mfxStatus CMC::IM_SURF_SET(
514     AbstractSurfaceHandle   pD3DSurf,
515     CmSurface2D          ** p_surface,
516     SurfaceIndex         ** p_idxSurf
517 )
518 {
519     res = device->CreateSurface2D(pD3DSurf, *p_surface);
520     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
521     res = (*p_surface)->GetIndex(*p_idxSurf);
522     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
523     return MFX_ERR_NONE;
524 }
525 
IM_MRE_SURF_SET(CmSurface2D ** p_Surface,SurfaceIndex ** p_idxSurf)526 mfxStatus CMC::IM_MRE_SURF_SET(
527     CmSurface2D  ** p_Surface,
528     SurfaceIndex ** p_idxSurf
529 )
530 {
531     mfxU32
532         width = SUBMREDIM, height = SUBMREDIM;
533     res = device->CreateSurface2D(width * sizeof(mfxI16Pair), height, CM_SURFACE_FORMAT_A8, *p_Surface);
534     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
535     res = (*p_Surface)->GetIndex(*p_idxSurf);
536     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
537     return MFX_ERR_NONE;
538 }
539 
IM_SURF_SET_Int()540 mfxStatus CMC::IM_SURF_SET_Int() {
541     for (mfxU32 i = 0; i < QfIn.size(); i++) {
542         res += IM_SURF_SET(&QfIn[i].frameData, &QfIn[i].fIdx);
543         QfIn[i].scene_idx = 0;
544     }
545     return MFX_ERR_NONE;
546 }
547 
IM_SURF_SET()548 mfxStatus CMC::IM_SURF_SET()
549 {
550     for (mfxU32 i = 0; i < QfIn.size(); i++)
551     {
552         MFX_SAFE_CALL(IM_MRE_SURF_SET(&QfIn[i].magData, &QfIn[i].idxMag));
553         mfxHDLPair
554             handle;
555         // if a surface is opaque, need to extract normal surface
556         mfxFrameSurface1
557             * pSurf = m_pCore->GetNativeSurface(QfIn[i].mfxFrame);
558         QfIn[i].mfxFrame = pSurf ? pSurf : QfIn[i].mfxFrame;
559         // GetFrameHDL is used as QfIn[].mfxFrme is allocated via call to Core Alloc function
560         MFX_SAFE_CALL(m_pCore->GetFrameHDL(QfIn[i].mfxFrame->Data.MemId, reinterpret_cast<mfxHDL*>(&handle)));
561         MFX_SAFE_CALL(IM_SURF_SET(reinterpret_cast<AbstractSurfaceHandle>(handle.first), &QfIn[i].frameData, &QfIn[i].fIdx));
562         QfIn[i].scene_idx = 0;
563     }
564     return MFX_ERR_NONE;
565 }
566 
MCTF_QUERY_NUMBER_OF_REFERENCES()567 mfxU16  CMC::MCTF_QUERY_NUMBER_OF_REFERENCES()
568 {
569     return number_of_References;
570 }
571 
MCTF_GetQueueDepth()572 mfxU32 CMC::MCTF_GetQueueDepth()
573 {
574     return (mfxU32)QfIn.size();
575 }
576 
MCTF_SetMemory(const std::vector<mfxFrameSurface1 * > & mfxSurfPool)577 mfxStatus CMC::MCTF_SetMemory(
578     const std::vector<mfxFrameSurface1*> & mfxSurfPool
579 )
580 {
581     if (mfxSurfPool.size() != QfIn.size())
582         return MFX_ERR_UNDEFINED_BEHAVIOR;
583     else
584     {
585         auto inp_iter = mfxSurfPool.begin();
586         for (auto it = QfIn.begin(); it != QfIn.end() && inp_iter != mfxSurfPool.end(); ++it, ++inp_iter)
587             it->mfxFrame = *inp_iter;
588         res = IM_SURF_SET();
589         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
590         // mco & idxmco will be extracted from an output surface
591         mco = nullptr;
592         res = IM_SURF_SET(&mco2, &idxMco2);
593         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
594 
595         //Setup for 2 references
596         res = GEN_SURF_SET(&mv_1, &mvSys1, &idxMv_1);
597         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
598         res = GEN_SURF_SET(&mv_2, &mvSys2, &idxMv_2);
599         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
600         if (number_of_References > 2)
601         {
602         //Setup for 4 references
603         res = GEN_SURF_SET(&mv_3, &mvSys3, &idxMv_3);
604         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
605         res = GEN_SURF_SET(&mv_4, &mvSys4, &idxMv_4);
606         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
607         }
608 
609         res = GEN_SURF_SET(&distSurf, &distSys, &idxDist);
610         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
611         res = GEN_NoiseSURF_SET(&noiseAnalysisSurf, &noiseAnalysisSys, &idxNoiseAnalysis);
612         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
613         return MFX_ERR_NONE;
614     }
615 }
616 
MCTF_SetMemory(bool isCmUsed)617 mfxStatus CMC::MCTF_SetMemory(
618     bool isCmUsed
619 )
620 {
621         // mco & idxmco will be extracted from input/output surface
622         if (!isCmUsed)
623         {
624             res = IM_SURF_SET_Int();
625             MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
626         }
627         mco     = nullptr;
628         idxMco  = nullptr;
629         mco2    = nullptr;
630         idxMco2 = nullptr;
631 
632         //Setup for 2 references
633         res = GEN_SURF_SET(&mv_1, &mvSys1, &idxMv_1);
634         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
635         res = GEN_SURF_SET(&mv_2, &mvSys2, &idxMv_2);
636         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
637         if (number_of_References > 2)
638         {
639             //Setup for 4 references
640             res = GEN_SURF_SET(&mv_3, &mvSys3, &idxMv_3);
641             MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
642             res = GEN_SURF_SET(&mv_4, &mvSys4, &idxMv_4);
643             MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
644         }
645 
646         res = GEN_SURF_SET(&distSurf, &distSys, &idxDist);
647         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
648         res = GEN_NoiseSURF_SET(&noiseAnalysisSurf, &noiseAnalysisSys, &idxNoiseAnalysis);
649         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
650         return MFX_ERR_NONE;
651 }
652 
MCTF_INIT(VideoCORE * core,CmDevice * pCmDevice,const mfxFrameInfo & FrameInfo,const IntMctfParams * pMctfParam,bool isCmUsed,const bool externalSCD,const bool useFilterAdaptControl,const bool isNCActive)653 mfxStatus CMC::MCTF_INIT(
654     VideoCORE           * core,
655     CmDevice            * pCmDevice,
656     const mfxFrameInfo  & FrameInfo,
657     const IntMctfParams * pMctfParam,
658     bool                  isCmUsed,
659     const bool            externalSCD,
660     const bool            useFilterAdaptControl,
661     const bool            isNCActive
662 )
663 {
664     version         = 400;
665     argIdx          = 0;
666     tsWidthFull     = 0;
667     tsWidth         = 0;
668     tsHeight        = 0;
669     bth             = 500;
670     blsize          = 16;
671     device          = NULL;
672     sceneNum        = 0;
673     countFrames     = 0;
674     firstFrame      = 1;
675     lastFrame       = 0;
676     exeTime         = 0;
677     exeTimeT        = 0;
678     m_externalSCD   = externalSCD;
679     m_adaptControl  = useFilterAdaptControl;
680     m_doFilterFrame = false;
681 
682     //--filter configuration parameters
683     m_AutoMode = MCTF_MODE::MCTF_NOT_INITIALIZED_MODE;
684     ConfigMode = MCTF_CONFIGURATION::MCTF_NOT_CONFIGURED;
685     number_of_References = MCTF_TEMPORAL_MODE_2REF;
686     bitrate_Adaptation = false;
687     deblocking_Control = MFX_CODINGOPTION_OFF;
688     bpp = 0.0;
689     m_FrameRateExtD = 1;
690     m_FrameRateExtN = 0;
691 
692     ctrlBuf = 0;
693     idxCtrl = 0;
694     distSys = 0;
695     time    = 0;
696 
697     qpel1   = 0;
698     qpel2   = 0;
699     idxMv_1 = 0;
700 
701     bufferCount = 0;
702     //ME elements
703     genxRefs1 = 0;
704     genxRefs2 = 0;
705     genxRefs3 = 0;
706     genxRefs4 = 0;
707     idxMv_1 = NULL;
708     idxMv_2 = NULL;
709     idxMv_3 = NULL;
710     idxMv_4 = NULL;
711 
712     //Motion Estimation
713     programMe = 0;
714     kernelMe  = 0;
715 
716     //MC elements
717     mco     = 0;
718     idxMco  = 0;
719     mco2    = 0;
720     idxMco2 = 0;
721 
722     //Motion Compensation
723     programMc   = 0;
724     kernelMcDen = 0;
725     kernelMc1r  = 0;
726     kernelMc2r  = 0;
727     kernelMc4r  = 0;
728     //Common elements
729     queue = NULL;
730     //copyQ  = NULL;
731     copyEv = NULL;
732 
733 //    m_IOPattern = io_pattern;
734 //    m_ioMode = io_mode;
735 
736     if (core)
737         m_pCore = core;
738     else
739         return MFX_ERR_NOT_INITIALIZED;
740 
741     if (pCmDevice)
742         device = pCmDevice;
743     else
744         return MFX_ERR_NOT_INITIALIZED;
745 
746     mfxStatus sts = MFX_ERR_NONE;
747     if(!m_externalSCD)
748         pSCD.reset(new(ASC));
749 
750     IntMctfParams MctfParam{};
751     QueryDefaultParams(&MctfParam);
752 
753     // if no MctfParams are passed, to use default
754     if (!pMctfParam)
755         pMctfParam = &MctfParam;
756     sts = MCTF_SET_ENV(core, FrameInfo, pMctfParam, isCmUsed, isNCActive);
757 
758     MFX_CHECK_STS(sts);
759     return sts;
760 }
761 
MCTF_INIT(VideoCORE * core,CmDevice * pCmDevice,const mfxFrameInfo & FrameInfo,const IntMctfParams * pMctfParam)762 mfxStatus CMC::MCTF_INIT(
763     VideoCORE           * core,
764     CmDevice            * pCmDevice,
765     const mfxFrameInfo  & FrameInfo,
766     const IntMctfParams * pMctfParam
767 )
768 {
769     return (MCTF_INIT(core, pCmDevice, FrameInfo, pMctfParam, false, false));
770 }
771 
MCTF_INIT(VideoCORE * core,CmDevice * pCmDevice,const mfxFrameInfo & FrameInfo,const IntMctfParams * pMctfParam,const bool externalSCD,const bool isNCActive)772 mfxStatus CMC::MCTF_INIT(
773     VideoCORE           * core,
774     CmDevice            * pCmDevice,
775     const mfxFrameInfo  & FrameInfo,
776     const IntMctfParams * pMctfParam,
777     const bool            externalSCD,
778     const bool            isNCActive
779 )
780 {
781     return (MCTF_INIT(core, pCmDevice, FrameInfo, pMctfParam, false, externalSCD, false, isNCActive));
782 }
783 
MCTF_SET_ENV(VideoCORE * core,const mfxFrameInfo & FrameInfo,const IntMctfParams * pMctfParam,bool isCmUsed,bool isNCActive)784 mfxStatus CMC::MCTF_SET_ENV(
785     VideoCORE           * core,
786     const mfxFrameInfo  & FrameInfo,
787     const IntMctfParams * pMctfParam,
788     bool                  isCmUsed,
789     bool                  isNCActive
790 )
791 {
792     IntMctfParams localMctfParam = *pMctfParam;
793     mfxStatus sts = MFX_ERR_NONE;
794     if (!device)
795         return MFX_ERR_NOT_INITIALIZED;
796 
797     hwSize = 4;
798     res = device->GetCaps(CAP_GPU_PLATFORM, hwSize, &hwType);
799     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
800 
801     if (core->GetHWType() >= MFX_HW_ICL)
802         res = device->CreateQueueEx(queue, CM_VME_QUEUE_CREATE_OPTION);
803     else
804         res = device->CreateQueue(queue);
805     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
806 
807     task = 0;
808     // --- bitrate
809     if (localMctfParam.BitsPerPixelx100k) //todo: to do correctcompare with 0.0
810         bitrate_Adaptation = true;
811     else
812         bitrate_Adaptation = false;
813 
814     // ---- BitsPerPixel
815     MCTF_UpdateBitrateInfo(localMctfParam.BitsPerPixelx100k);
816 
817     // --- deblock
818     if (MFX_CODINGOPTION_ON != localMctfParam.Deblocking &&
819         MFX_CODINGOPTION_OFF != localMctfParam.Deblocking &&
820         MFX_CODINGOPTION_UNKNOWN != localMctfParam.Deblocking)
821         return MFX_ERR_INVALID_VIDEO_PARAM;
822 
823     //Dimensions, control and io
824     if (MCTF_TEMPORAL_MODE_SPATIAL == localMctfParam.TemporalMode)
825     {
826         localMctfParam.Overlap = MFX_CODINGOPTION_OFF;
827         localMctfParam.Deblocking = MFX_CODINGOPTION_OFF;
828         localMctfParam.subPelPrecision = MFX_MVPRECISION_INTEGER;
829     }
830     deblocking_Control = localMctfParam.Deblocking;
831 
832     // MRE is initialized inside
833     sts = SetupMeControl(FrameInfo, localMctfParam.FilterStrength, localMctfParam.subPelPrecision);
834     MFX_CHECK_STS(sts);
835 
836     sts = MCTF_InitQueue(localMctfParam.TemporalMode);
837     MFX_CHECK_STS(sts);
838 
839     sts = DIM_SET(localMctfParam.Overlap);
840     MFX_CHECK_STS(sts);
841 
842     if (bitrate_Adaptation || !localMctfParam.FilterStrength)
843         m_AutoMode = MCTF_MODE::MCTF_AUTO_MODE;
844     else
845         m_AutoMode = MCTF_MODE::MCTF_MANUAL_MODE;
846 
847     if (bitrate_Adaptation)
848         ConfigMode = MCTF_CONFIGURATION::MCTF_AUT_CA_BA;
849     else
850     {
851         ConfigMode = MCTF_MODE::MCTF_AUTO_MODE == m_AutoMode ? MCTF_CONFIGURATION::MCTF_AUT_CA_NBA : MCTF_CONFIGURATION::MCTF_MAN_NCA_NBA;
852     }
853 
854     pMCTF_SpDen_func = nullptr;
855     pMCTF_NOA_func   = nullptr;
856     pMCTF_LOAD_func  = nullptr;
857     pMCTF_ME_func    = nullptr;
858     pMCTF_MERGE_func = nullptr;
859     pMCTF_func       = nullptr;
860 
861     pMCTF_func       = &CMC::MCTF_RUN_MCTF_DEN;
862     if (m_AutoMode == MCTF_MODE::MCTF_AUTO_MODE || isNCActive)
863         pMCTF_NOA_func = &CMC::noise_estimator;
864 
865     if (number_of_References == FOUR_REFERENCES)
866     {
867         pMCTF_LOAD_func = &CMC::MCTF_LOAD_4REF;
868         pMCTF_ME_func = &CMC::MCTF_RUN_ME_4REF;
869         pMCTF_MERGE_func = &CMC::MCTF_RUN_MERGE;
870     }
871     else if (number_of_References == TWO_REFERENCES)
872     {
873         pMCTF_LOAD_func = &CMC::MCTF_LOAD_2REF;
874         if (isNCActive)
875             pMCTF_ME_func = &CMC::MCTF_RUN_ME_2REF_HE;
876         else
877             pMCTF_ME_func = &CMC::MCTF_RUN_ME_2REF;
878         pMCTF_MERGE_func = NULL;
879     }
880     else if (number_of_References == ONE_REFERENCE)
881     {
882         pMCTF_func = &CMC::MCTF_RUN_MCTF_DEN_1REF;
883         pMCTF_LOAD_func = &CMC::MCTF_LOAD_1REF;
884         pMCTF_ME_func = &CMC::MCTF_RUN_ME_1REF;
885         pMCTF_MERGE_func = &CMC::MCTF_RUN_BLEND;
886     }
887     else if (number_of_References == NO_REFERENCES)
888     {
889         pMCTF_func = &CMC::MCTF_RUN_MCTF_DEN_1REF;
890         pMCTF_LOAD_func = &CMC::MCTF_LOAD_1REF;
891         pMCTF_ME_func = NULL;
892         pMCTF_MERGE_func = &CMC::MCTF_RUN_AMCTF;
893     }
894     else
895         return MFX_ERR_UNDEFINED_BEHAVIOR;
896 
897     //deblocking only if ME is used
898     if (MFX_CODINGOPTION_ON == deblocking_Control &&
899         (ONE_REFERENCE == number_of_References ||
900          TWO_REFERENCES == number_of_References ||
901          FOUR_REFERENCES == number_of_References)
902         )
903         pMCTF_SpDen_func = &CMC::MCTF_RUN_Denoise;
904 
905     if (blsize < VMEBLSIZE)
906         p_ctrl->th = p_ctrl->th / 4;
907     res = device->CreateBuffer(sizeof(MeControlSmall), ctrlBuf);
908     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
909     res = ctrlBuf->WriteSurface((const uint8_t *)p_ctrl.get(), NULL, sizeof(MeControlSmall));
910     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
911     res = ctrlBuf->GetIndex(idxCtrl);
912     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
913 
914     //Init internal buffer which is not shared
915     if (isNCActive)
916     {
917         res = MCTF_SetMemory(isCmUsed);
918         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
919     }
920 
921     //Motion Estimation
922     switch (hwType)
923     {
924 #ifdef MFX_ENABLE_KERNELS
925     case PLATFORM_INTEL_BDW:
926         res = device->LoadProgram((void *)genx_me_gen8, sizeof(genx_me_gen8), programMe, "nojitter");
927         break;
928     case PLATFORM_INTEL_ICL:
929         res = device->LoadProgram((void *)genx_me_gen11, sizeof(genx_me_gen11), programMe, "nojitter");
930         break;
931     case PLATFORM_INTEL_ICLLP:
932         res = device->LoadProgram((void *)genx_me_gen11lp, sizeof(genx_me_gen11lp), programMe, "nojitter");
933         break;
934     case PLATFORM_INTEL_TGLLP:
935     case PLATFORM_INTEL_RKL:
936     case PLATFORM_INTEL_DG1:
937         res = device->LoadProgram((void *)genx_me_gen12lp, sizeof(genx_me_gen12lp), programMe, "nojitter");
938         break;
939     case PLATFORM_INTEL_SKL:
940     case PLATFORM_INTEL_BXT:
941     case PLATFORM_INTEL_CNL:
942     case PLATFORM_INTEL_KBL:
943     case PLATFORM_INTEL_CFL:
944     case PLATFORM_INTEL_GLK:
945         res = device->LoadProgram((void *)genx_me_gen9, sizeof(genx_me_gen9), programMe, "nojitter");
946         break;
947 #endif
948     default:
949         return MFX_ERR_UNSUPPORTED;
950     }
951     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
952 
953     //ME Kernel
954     if (MFX_CODINGOPTION_ON == overlap_Motion)
955     {
956         res = device->CreateKernel(programMe, CM_KERNEL_FUNCTION(MeP16_1MV_MRE), kernelMe);
957         res = device->CreateKernel(programMe, CM_KERNEL_FUNCTION(MeP16bi_1MV2_MRE), kernelMeB);
958         res = device->CreateKernel(programMe, CM_KERNEL_FUNCTION(MeP16bi_1MV2_MRE), kernelMeB2);
959 
960     }
961     else
962     if (MFX_CODINGOPTION_OFF == overlap_Motion || MFX_CODINGOPTION_UNKNOWN == overlap_Motion)
963     {
964         res = device->CreateKernel(programMe, CM_KERNEL_FUNCTION(MeP16_1MV_MRE_8x8), kernelMe);
965         if (isNCActive)
966         {
967             res = device->CreateKernel(programMe, CM_KERNEL_FUNCTION(MeP16_1ME_2BiRef_MRE_8x8), kernelMeB);
968             res = device->CreateKernel(programMe, CM_KERNEL_FUNCTION(MeP16_1ME_2BiRef_MRE_8x8), kernelMeB2);
969         }
970         else
971         {
972             res = device->CreateKernel(programMe, CM_KERNEL_FUNCTION(MeP16bi_1MV2_MRE_8x8), kernelMeB);
973             res = device->CreateKernel(programMe, CM_KERNEL_FUNCTION(MeP16bi_1MV2_MRE_8x8), kernelMeB2);
974         }
975 
976     }
977     else
978         return MFX_ERR_INVALID_VIDEO_PARAM;
979     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
980 
981     //Motion Compensation
982     switch (hwType)
983     {
984 #ifdef MFX_ENABLE_KERNELS
985     case PLATFORM_INTEL_BDW:
986         res = device->LoadProgram((void *)genx_mc_gen8, sizeof(genx_mc_gen8), programMc, "nojitter");
987         break;
988     case PLATFORM_INTEL_ICL:
989         res = device->LoadProgram((void *)genx_mc_gen11, sizeof(genx_mc_gen11), programMc, "nojitter");
990         break;
991     case PLATFORM_INTEL_ICLLP:
992         res = device->LoadProgram((void *)genx_mc_gen11lp, sizeof(genx_mc_gen11lp), programMc, "nojitter");
993         break;
994     case PLATFORM_INTEL_TGLLP:
995     case PLATFORM_INTEL_RKL:
996     case PLATFORM_INTEL_DG1:
997         res = device->LoadProgram((void *)genx_mc_gen12lp, sizeof(genx_mc_gen12lp), programMc, "nojitter");
998         break;
999     case PLATFORM_INTEL_SKL:
1000     case PLATFORM_INTEL_BXT:
1001     case PLATFORM_INTEL_CNL:
1002     case PLATFORM_INTEL_KBL:
1003     case PLATFORM_INTEL_CFL:
1004     case PLATFORM_INTEL_GLK:
1005         res = device->LoadProgram((void *)genx_mc_gen9, sizeof(genx_mc_gen9), programMc, "nojitter");
1006         break;
1007 #endif
1008     default:
1009         return MFX_ERR_UNSUPPORTED;
1010     }
1011     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1012 
1013     switch (hwType)
1014     {
1015 #ifdef MFX_ENABLE_KERNELS
1016     case PLATFORM_INTEL_BDW:
1017         res = device->LoadProgram((void *)genx_sd_gen8, sizeof(genx_sd_gen8), programDe, "nojitter");
1018         break;
1019     case PLATFORM_INTEL_ICL:
1020         res = device->LoadProgram((void *)genx_sd_gen11, sizeof(genx_sd_gen11), programDe, "nojitter");
1021         break;
1022     case PLATFORM_INTEL_ICLLP:
1023         res = device->LoadProgram((void *)genx_sd_gen11lp, sizeof(genx_sd_gen11lp), programDe, "nojitter");
1024         break;
1025     case PLATFORM_INTEL_TGLLP:
1026     case PLATFORM_INTEL_RKL:
1027     case PLATFORM_INTEL_DG1:
1028         res = device->LoadProgram((void *)genx_sd_gen12lp, sizeof(genx_sd_gen12lp), programDe, "nojitter");
1029         break;
1030     case PLATFORM_INTEL_SKL:
1031     case PLATFORM_INTEL_BXT:
1032     case PLATFORM_INTEL_CNL:
1033     case PLATFORM_INTEL_KBL:
1034     case PLATFORM_INTEL_CFL:
1035     case PLATFORM_INTEL_GLK:
1036         res = device->LoadProgram((void *)genx_sd_gen9, sizeof(genx_sd_gen9), programDe, "nojitter");
1037         break;
1038 #endif
1039     default:
1040         return MFX_ERR_UNSUPPORTED;
1041     }
1042     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1043 
1044     //Denoising No reference Kernel
1045     res = device->CreateKernel(programDe, CM_KERNEL_FUNCTION(SpatialDenoiser_8x8_NV12), kernelMcDen);
1046     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1047     //Motion Compensation 1 Ref Kernel
1048     res = device->CreateKernel(programMc, CM_KERNEL_FUNCTION(McP16_4MV_1SURF_WITH_CHR), kernelMc1r);
1049     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1050     //Motion Compensation 2 Ref Kernel
1051     res = device->CreateKernel(programMc, CM_KERNEL_FUNCTION(McP16_4MV_2SURF_WITH_CHR), kernelMc2r);
1052     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1053     //Motion Compensation 4 Ref Kernel
1054     if (number_of_References == FOUR_REFERENCES) {
1055         res = device->CreateKernel(programMc, CM_KERNEL_FUNCTION(MC_MERGE4), kernelMc4r);
1056         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1057     }
1058 
1059     res = device->CreateKernel(programMc, CM_KERNEL_FUNCTION(MC_VAR_SC_CALC), kernelNoise);
1060     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1061     if (!m_externalSCD)
1062     {
1063         sts = pSCD->Init(p_ctrl->CropW, p_ctrl->CropH, p_ctrl->width, MFX_PICSTRUCT_PROGRESSIVE, device);
1064         MFX_CHECK_STS(sts);
1065         sts = pSCD->SetGoPSize(Immediate_GoP);
1066         MFX_CHECK_STS(sts);
1067         pSCD->SetControlLevel(0);
1068     }
1069     if (m_AutoMode == MCTF_MODE::MCTF_AUTO_MODE)
1070     {
1071         sts = SetFilterStrenght(DEFAULT_FILTER_STRENGTH);
1072         m_RTParams.FilterStrength = DEFAULT_FILTER_STRENGTH;
1073     }
1074     else
1075     {
1076         if (isNCActive)
1077         {
1078             sts = SetFilterStrenght(INPIPE_FILTER_STRENGTH);
1079             m_RTParams.FilterStrength = INPIPE_FILTER_STRENGTH;
1080         }
1081         else
1082         {
1083             sts = SetFilterStrenght(localMctfParam.FilterStrength);
1084             m_RTParams.FilterStrength = localMctfParam.FilterStrength;
1085         }
1086     }
1087     // now initialize run-time parameters
1088     m_RTParams = localMctfParam;
1089     m_InitRTParams = m_RTParams;
1090 
1091     return sts;
1092 }
MCTF_CheckRTParams(const IntMctfParams * pMctfControl)1093 mfxStatus CMC::MCTF_CheckRTParams(
1094     const IntMctfParams * pMctfControl
1095 )
1096 {
1097     mfxStatus sts = MFX_ERR_NONE;
1098     if (pMctfControl)
1099     {
1100 #ifdef MFX_ENABLE_MCTF_EXT
1101     // check BPP for max value. the threshold must be adjusted for higher bit-depths
1102         if (pMctfControl->BitsPerPixelx100k > (DEFAULT_BPP))
1103             sts = MFX_ERR_INVALID_VIDEO_PARAM;
1104 #endif
1105         if (pMctfControl->FilterStrength > 21)
1106             sts = MFX_ERR_INVALID_VIDEO_PARAM;
1107     }
1108     return sts;
1109 }
MCTF_UpdateRTParams(IntMctfParams * pMctfControl)1110 mfxStatus CMC::MCTF_UpdateRTParams(
1111     IntMctfParams * pMctfControl
1112 )
1113 {
1114     mfxStatus  sts = MCTF_CheckRTParams(pMctfControl);
1115 
1116     if (pMctfControl && MFX_ERR_NONE == sts)
1117         m_RTParams = *pMctfControl;
1118     else
1119         m_RTParams = m_InitRTParams;
1120     return MFX_ERR_NONE;
1121 }
MCTF_UpdateANDApplyRTParams(mfxU8 srcNum)1122 mfxStatus CMC::MCTF_UpdateANDApplyRTParams(
1123     mfxU8 srcNum
1124 )
1125 {
1126     // deblock can be controled for every mode
1127     if (MCTF_CONFIGURATION::MCTF_MAN_NCA_NBA == ConfigMode ||
1128         MCTF_CONFIGURATION::MCTF_AUT_CA_BA == ConfigMode ||
1129         MCTF_CONFIGURATION::MCTF_AUT_CA_NBA == ConfigMode)
1130     {
1131 
1132 #ifdef MCTF_UPDATE_RT_FRAME_ORDER_BASED
1133         m_RTParams = QfIn[srcNum].mfxMctfControl;
1134 #else
1135         (void)srcNum;
1136 #endif
1137         if (MCTF_CONFIGURATION::MCTF_MAN_NCA_NBA == ConfigMode)
1138         {
1139             SetFilterStrenght(m_RTParams.FilterStrength);
1140         }
1141 #ifdef MFX_ENABLE_MCTF_EXT
1142         deblocking_Control = m_RTParams.Deblocking;
1143         //deblocking only if ME is used
1144         if (MFX_CODINGOPTION_ON == deblocking_Control &&
1145             (ONE_REFERENCE == number_of_References ||
1146                 TWO_REFERENCES == number_of_References ||
1147                 FOUR_REFERENCES == number_of_References)
1148             )
1149             pMCTF_SpDen_func = &CMC::MCTF_RUN_Denoise;
1150         else
1151             pMCTF_SpDen_func = NULL;
1152 
1153         if (MCTF_CONFIGURATION::MCTF_AUT_CA_BA == ConfigMode)
1154             MFX_SAFE_CALL (MCTF_UpdateBitrateInfo(m_RTParams.BitsPerPixelx100k));
1155 #endif
1156     }
1157     return MFX_ERR_NONE;
1158 }
1159 
1160 // todo: what if bitrate is close to 0?
MCTF_UpdateBitrateInfo(mfxU32 BitsPerPexelx100k)1161 mfxStatus CMC::MCTF_UpdateBitrateInfo(
1162     mfxU32 BitsPerPexelx100k
1163 )
1164 {
1165     if (MCTF_CONFIGURATION::MCTF_NOT_CONFIGURED == ConfigMode ||
1166         MCTF_CONFIGURATION::MCTF_AUT_CA_BA == ConfigMode )
1167     {
1168         // todo: intially here was a code that uses 12bpp in case
1169         // of no bitrate or FPS numerator are passed;
1170         // what should be now?
1171         bpp = BitsPerPexelx100k * 1.0 / MCTF_BITRATE_MULTIPLIER;
1172         return MFX_ERR_NONE;
1173     }
1174     else
1175     {
1176         // if any other mode, update the bitrate does not have any effect;
1177         // let notify a caller about this;
1178         // however, its not critical as MCTF can operate further
1179         return MFX_WRN_VALUE_NOT_CHANGED;
1180     }
1181 }
1182 
GEN_NoiseSURF_SET(CmSurface2DUP ** p_Surface,void ** p_Sys,SurfaceIndex ** p_idxSurf)1183 mfxStatus CMC::GEN_NoiseSURF_SET(
1184     CmSurface2DUP ** p_Surface,
1185     void          ** p_Sys,
1186     SurfaceIndex  ** p_idxSurf
1187 )
1188 {
1189     surfNoisePitch = 0;
1190     surfNoiseSize = 0;
1191     res = device->GetSurface2DInfo(DIVUP(p_ctrl->CropW, 16) * sizeof(spatialNoiseAnalysis), DIVUP(p_ctrl->CropH, 16), CM_SURFACE_FORMAT_A8, surfNoisePitch, surfNoiseSize);
1192     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1193 
1194     *p_Sys = CM_ALIGNED_MALLOC(surfNoiseSize, 0x1000);
1195     MFX_CHECK(*p_Sys, MFX_ERR_NULL_PTR);
1196     memset(*p_Sys, 0, surfNoiseSize);
1197     res = device->CreateSurface2DUP(DIVUP(p_ctrl->CropW, 16) * sizeof(spatialNoiseAnalysis), DIVUP(p_ctrl->CropH, 16), CM_SURFACE_FORMAT_A8, *p_Sys, *p_Surface);
1198     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1199     res = (*p_Surface)->GetIndex(*p_idxSurf);
1200     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1201     return MFX_ERR_NONE;
1202 }
GEN_SURF_SET(CmSurface2DUP ** p_Surface,void ** p_Sys,SurfaceIndex ** p_idxSurf)1203 mfxStatus CMC::GEN_SURF_SET(
1204     CmSurface2DUP ** p_Surface,
1205     void          ** p_Sys,
1206     SurfaceIndex  **p_idxSurf
1207 )
1208 {
1209     surfPitch = 0;
1210     surfSize = 0;
1211     res = device->GetSurface2DInfo(ov_width_bl * sizeof(mfxI16Pair), ov_height_bl, CM_SURFACE_FORMAT_A8, surfPitch, surfSize);
1212     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1213     *p_Sys = CM_ALIGNED_MALLOC(surfSize, 0x1000);
1214     MFX_CHECK(*p_Sys, MFX_ERR_NULL_PTR);
1215     memset(*p_Sys, 0, surfSize);
1216     res = device->CreateSurface2DUP(ov_width_bl * sizeof(mfxI16Pair), ov_height_bl, CM_SURFACE_FORMAT_A8, *p_Sys, *p_Surface);
1217     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1218     res = (*p_Surface)->GetIndex(*p_idxSurf);
1219     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1220     return MFX_ERR_NONE;
1221 }
1222 
MCTF_GetEmptySurface(mfxFrameSurface1 ** ppSurface)1223 mfxStatus CMC::MCTF_GetEmptySurface(
1224     mfxFrameSurface1 ** ppSurface
1225 )
1226 {
1227     size_t buffer_size = QfIn.size() - 1;
1228     if (bufferCount > buffer_size)
1229         return MFX_ERR_UNDEFINED_BEHAVIOR;
1230     if (QfIn[bufferCount].mfxFrame->Data.Locked)
1231     {
1232         *ppSurface = nullptr;
1233         return MFX_ERR_NONE;
1234     }
1235     else
1236     {
1237         m_pCore->IncreaseReference(&(QfIn[bufferCount].mfxFrame->Data));
1238         *ppSurface = QfIn[bufferCount].mfxFrame;
1239         return MFX_ERR_NONE;
1240     }
1241 }
1242 
MCTF_PUT_FRAME(mfxU32 sceneNumber,CmSurface2D * OutSurf)1243 mfxStatus CMC::MCTF_PUT_FRAME(
1244     mfxU32 sceneNumber,
1245     CmSurface2D* OutSurf
1246 )
1247 {
1248     size_t buffer_size = QfIn.size() - 1;
1249     if (bufferCount > buffer_size)
1250     {
1251 #ifdef MFX_MCTF_DEBUG_PRINT
1252         ASC_PRINTF("Error: Invalid frame buffer position\n");
1253 #endif
1254         return MFX_ERR_UNDEFINED_BEHAVIOR;
1255     }
1256 
1257 #ifdef MCTF_UPDATE_RT_FRAME_ORDER_BASED
1258     QfIn[bufferCount].mfxMctfControl = m_RTParams;
1259 #endif
1260     QfIn[bufferCount].scene_idx = sceneNumber;
1261     QfIn[bufferCount].frame_number = countFrames;
1262 
1263     // if outFrame is nullptr, it means we cannot output result;
1264     if (OutSurf)
1265     {
1266         mco = OutSurf;
1267         INT cmSts = OutSurf->GetIndex(idxMco);
1268         MFX_CHECK((CM_SUCCESS == cmSts), MFX_ERR_DEVICE_FAILED);
1269     }
1270     return MFX_ERR_NONE;
1271 }
1272 
MCTF_UpdateBufferCount()1273 mfxStatus CMC::MCTF_UpdateBufferCount()
1274 {
1275     size_t buffer_size = QfIn.size() - 1;
1276     if (bufferCount > buffer_size)
1277         return MFX_ERR_UNDEFINED_BEHAVIOR;
1278     bufferCount = (bufferCount < buffer_size) ? bufferCount + 1 : buffer_size;
1279     return MFX_ERR_NONE;
1280 }
1281 
MCTF_LOAD_1REF()1282 mfxI32 CMC::MCTF_LOAD_1REF()
1283 {
1284     res = device->CreateVmeSurfaceG7_5(QfIn[1].frameData, &QfIn[0].frameData, NULL, 1, 0, genxRefs1);
1285     MCTF_CHECK_CM_ERR(res, res);
1286     return res;
1287 }
1288 
MCTF_LOAD_2REF()1289 mfxI32 CMC::MCTF_LOAD_2REF()
1290 {
1291     res = device->CreateVmeSurfaceG7_5(QfIn[1].frameData, &QfIn[0].frameData, &QfIn[2].frameData, 1, 1, genxRefs1);
1292     MCTF_CHECK_CM_ERR(res, res);
1293     res = device->CreateVmeSurfaceG7_5(QfIn[1].frameData, &QfIn[2].frameData, NULL, 1, 0, genxRefs2);
1294     MCTF_CHECK_CM_ERR(res, res);
1295     return res;
1296 }
1297 
MCTF_LOAD_4REF()1298 mfxI32 CMC::MCTF_LOAD_4REF()
1299 {
1300     res = device->CreateVmeSurfaceG7_5(QfIn[2].frameData, &QfIn[1].frameData, &QfIn[3].frameData, 1, 1, genxRefs1);
1301     MCTF_CHECK_CM_ERR(res, res);
1302     res = device->CreateVmeSurfaceG7_5(QfIn[2].frameData, &QfIn[3].frameData, NULL, 1, 0, genxRefs2);
1303     MCTF_CHECK_CM_ERR(res, res);
1304     res = device->CreateVmeSurfaceG7_5(QfIn[2].frameData, &QfIn[0].frameData, &QfIn[4].frameData, 1, 1, genxRefs3);
1305     MCTF_CHECK_CM_ERR(res, res);
1306     res = device->CreateVmeSurfaceG7_5(QfIn[2].frameData, &QfIn[4].frameData, NULL, 1, 0, genxRefs4);
1307     MCTF_CHECK_CM_ERR(res, res);
1308     return res;
1309 }
1310 
MCTF_SET_KERNELMe(SurfaceIndex * GenxRefs,SurfaceIndex * idxMV,mfxU16 start_x,mfxU16 start_y,mfxU8 blSize)1311 mfxI32 CMC::MCTF_SET_KERNELMe(
1312     SurfaceIndex * GenxRefs,
1313     SurfaceIndex * idxMV,
1314     mfxU16         start_x,
1315     mfxU16         start_y,
1316     mfxU8          blSize)
1317 {
1318     argIdx = 0;
1319     res = kernelMe->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1320     MCTF_CHECK_CM_ERR(res, res);
1321     res = kernelMe->SetKernelArg(argIdx++, sizeof(*GenxRefs), GenxRefs);
1322     MCTF_CHECK_CM_ERR(res, res);
1323     res = kernelMe->SetKernelArg(argIdx++, sizeof(*idxDist), idxDist);
1324     MCTF_CHECK_CM_ERR(res, res);
1325     res = kernelMe->SetKernelArg(argIdx++, sizeof(*idxMV), idxMV);
1326     MCTF_CHECK_CM_ERR(res, res);
1327     // set start mb
1328     mfxU16Pair start_xy = { start_x, start_y };
1329     res = kernelMe->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1330     MCTF_CHECK_CM_ERR(res, res);
1331     res = kernelMe->SetKernelArg(argIdx++, sizeof(blSize), &blSize);
1332     MCTF_CHECK_CM_ERR(res, res);
1333     return res;
1334 }
1335 
MCTF_SET_KERNELMeBi(SurfaceIndex * GenxRefs,SurfaceIndex * GenxRefs2,SurfaceIndex * idxMV,SurfaceIndex * idxMV2,mfxU16 start_x,mfxU16 start_y,mfxU8 blSize,mfxI8 forwardRefDist,mfxI8 backwardRefDist)1336 mfxI32 CMC::MCTF_SET_KERNELMeBi(
1337     SurfaceIndex * GenxRefs,
1338     SurfaceIndex * GenxRefs2,
1339     SurfaceIndex * idxMV,
1340     SurfaceIndex * idxMV2,
1341     mfxU16         start_x,
1342     mfxU16         start_y,
1343     mfxU8          blSize,
1344     mfxI8          forwardRefDist,
1345     mfxI8          backwardRefDist
1346 )
1347 {
1348     argIdx = 0;
1349     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1350     MCTF_CHECK_CM_ERR(res, res);
1351     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*GenxRefs), GenxRefs);
1352     MCTF_CHECK_CM_ERR(res, res);
1353     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*GenxRefs2), GenxRefs2);
1354     MCTF_CHECK_CM_ERR(res, res);
1355     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*idxDist), idxDist);
1356     MCTF_CHECK_CM_ERR(res, res);
1357     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*idxMV), idxMV);
1358     MCTF_CHECK_CM_ERR(res, res);
1359     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*idxMV2), idxMV2);
1360     MCTF_CHECK_CM_ERR(res, res);
1361     // set start mb
1362     mfxU16Pair start_xy = { start_x, start_y };
1363     res = kernelMeB->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1364     MCTF_CHECK_CM_ERR(res, res);
1365     res = kernelMeB->SetKernelArg(argIdx++, sizeof(blSize), &blSize);
1366     MCTF_CHECK_CM_ERR(res, res);
1367     res = kernelMeB->SetKernelArg(argIdx++, sizeof(forwardRefDist), &forwardRefDist);
1368     MCTF_CHECK_CM_ERR(res, res);
1369     res = kernelMeB->SetKernelArg(argIdx++, sizeof(backwardRefDist), &backwardRefDist);
1370     MCTF_CHECK_CM_ERR(res, res);
1371     return res;
1372 }
1373 
MCTF_SET_KERNELMeBiMRE(SurfaceIndex * GenxRefs,SurfaceIndex * GenxRefs2,SurfaceIndex * idxMV,SurfaceIndex * idxMV2,mfxU16 start_x,mfxU16 start_y,mfxU8 blSize,mfxI8 forwardRefDist,mfxI8 backwardRefDist)1374 mfxU32 CMC::MCTF_SET_KERNELMeBiMRE(
1375     SurfaceIndex* GenxRefs, SurfaceIndex* GenxRefs2,
1376     SurfaceIndex* idxMV, SurfaceIndex* idxMV2,
1377     mfxU16 start_x, mfxU16 start_y, mfxU8 blSize,
1378     mfxI8 forwardRefDist, mfxI8 backwardRefDist) {
1379     argIdx = 0;
1380     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1381     MCTF_CHECK_CM_ERR(res, res);
1382     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*GenxRefs), GenxRefs);
1383     MCTF_CHECK_CM_ERR(res, res);
1384     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*GenxRefs2), GenxRefs2);
1385     MCTF_CHECK_CM_ERR(res, res);
1386     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*idxDist), idxDist);
1387     MCTF_CHECK_CM_ERR(res, res);
1388     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*idxMV), idxMV);
1389     MCTF_CHECK_CM_ERR(res, res);
1390     res = kernelMeB->SetKernelArg(argIdx++, sizeof(*idxMV2), idxMV2);
1391     MCTF_CHECK_CM_ERR(res, res);
1392     // set start mb
1393     mfxU16Pair start_xy = { start_x, start_y };
1394     res = kernelMeB->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1395     MCTF_CHECK_CM_ERR(res, res);
1396     res = kernelMeB->SetKernelArg(argIdx++, sizeof(blSize), &blSize);
1397     MCTF_CHECK_CM_ERR(res, res);
1398     res = kernelMeB->SetKernelArg(argIdx++, sizeof(forwardRefDist), &forwardRefDist);
1399     MCTF_CHECK_CM_ERR(res, res);
1400     res = kernelMeB->SetKernelArg(argIdx++, sizeof(backwardRefDist), &backwardRefDist);
1401     MCTF_CHECK_CM_ERR(res, res);
1402     return res;
1403 }
1404 
MCTF_SET_KERNELMeBiMRE2(SurfaceIndex * GenxRefs,SurfaceIndex * GenxRefs2,SurfaceIndex * idxMV,SurfaceIndex * idxMV2,mfxU16 start_x,mfxU16 start_y,mfxU8 blSize,mfxI8 forwardRefDist,mfxI8 backwardRefDist)1405 mfxU32 CMC::MCTF_SET_KERNELMeBiMRE2(
1406     SurfaceIndex* GenxRefs, SurfaceIndex* GenxRefs2,
1407     SurfaceIndex* idxMV, SurfaceIndex* idxMV2,
1408     mfxU16 start_x, mfxU16 start_y, mfxU8 blSize,
1409     mfxI8 forwardRefDist, mfxI8 backwardRefDist) {
1410     argIdx = 0;
1411     res = kernelMeB2->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1412     MCTF_CHECK_CM_ERR(res, res);
1413     res = kernelMeB2->SetKernelArg(argIdx++, sizeof(*GenxRefs), GenxRefs);
1414     MCTF_CHECK_CM_ERR(res, res);
1415     res = kernelMeB2->SetKernelArg(argIdx++, sizeof(*GenxRefs2), GenxRefs2);
1416     MCTF_CHECK_CM_ERR(res, res);
1417     res = kernelMeB2->SetKernelArg(argIdx++, sizeof(*idxDist), idxDist);
1418     MCTF_CHECK_CM_ERR(res, res);
1419     res = kernelMeB2->SetKernelArg(argIdx++, sizeof(*idxMV), idxMV);
1420     MCTF_CHECK_CM_ERR(res, res);
1421     res = kernelMeB2->SetKernelArg(argIdx++, sizeof(*idxMV2), idxMV2);
1422     MCTF_CHECK_CM_ERR(res, res);
1423     // set start mb
1424     mfxU16Pair start_xy = { start_x, start_y };
1425     res = kernelMeB2->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1426     MCTF_CHECK_CM_ERR(res, res);
1427     res = kernelMeB2->SetKernelArg(argIdx++, sizeof(blSize), &blSize);
1428     MCTF_CHECK_CM_ERR(res, res);
1429     res = kernelMeB2->SetKernelArg(argIdx++, sizeof(forwardRefDist), &forwardRefDist);
1430     MCTF_CHECK_CM_ERR(res, res);
1431     res = kernelMeB2->SetKernelArg(argIdx++, sizeof(backwardRefDist), &backwardRefDist);
1432     MCTF_CHECK_CM_ERR(res, res);
1433     return res;
1434 }
1435 
MCTF_SET_KERNELMc(mfxU16 start_x,mfxU16 start_y,mfxU8 srcNum,mfxU8 refNum)1436 mfxI32 CMC::MCTF_SET_KERNELMc(
1437     mfxU16 start_x,
1438     mfxU16 start_y,
1439     mfxU8 srcNum,
1440     mfxU8 refNum
1441 )
1442 {
1443     argIdx = 0;
1444     res = kernelMc1r->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1445     MCTF_CHECK_CM_ERR(res, res);
1446     res = kernelMc1r->SetKernelArg(argIdx++, sizeof(*QfIn[refNum].fIdx), QfIn[refNum].fIdx);
1447     MCTF_CHECK_CM_ERR(res, res);
1448     res = kernelMc1r->SetKernelArg(argIdx++, sizeof(*idxMv_1), idxMv_1);
1449     MCTF_CHECK_CM_ERR(res, res);
1450     res = kernelMc1r->SetKernelArg(argIdx++, sizeof(*QfIn[srcNum].fIdx), QfIn[srcNum].fIdx);
1451     MCTF_CHECK_CM_ERR(res, res);
1452     res = kernelMc1r->SetKernelArg(argIdx++, sizeof(*idxMco), idxMco);
1453     MCTF_CHECK_CM_ERR(res, res);
1454     // set start mb
1455     mfxU16Pair start_xy = { start_x, start_y };
1456     res = kernelMc1r->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1457     MCTF_CHECK_CM_ERR(res, res);
1458     //scene numbers
1459     mfxU8quad scene_num_gpu = { (mfxU8)scene_numbers[0], (mfxU8)scene_numbers[1], (mfxU8)scene_numbers[2], 2 };
1460     res = kernelMc1r->SetKernelArg(argIdx++, sizeof(scene_num_gpu), &scene_num_gpu);
1461     MCTF_CHECK_CM_ERR(res, res);
1462     return res;
1463 
1464 }
1465 
MCTF_SET_KERNELMc2r(mfxU16 start_x,mfxU16 start_y)1466 mfxI32 CMC::MCTF_SET_KERNELMc2r(
1467     mfxU16 start_x,
1468     mfxU16 start_y
1469 )
1470 {
1471     argIdx = 0;
1472     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1473     MCTF_CHECK_CM_ERR(res, res);
1474     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*QfIn[0].fIdx), QfIn[0].fIdx);
1475     MCTF_CHECK_CM_ERR(res, res);
1476     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*idxMv_1), idxMv_1);
1477     MCTF_CHECK_CM_ERR(res, res);
1478     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*QfIn[2].fIdx), QfIn[2].fIdx);
1479     MCTF_CHECK_CM_ERR(res, res);
1480     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*idxMv_2), idxMv_2);
1481     MCTF_CHECK_CM_ERR(res, res);
1482     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*QfIn[1].fIdx), QfIn[1].fIdx);
1483     MCTF_CHECK_CM_ERR(res, res);
1484     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*idxMco), idxMco);
1485     MCTF_CHECK_CM_ERR(res, res);
1486     // set start mb
1487     mfxU16Pair start_xy = { start_x, start_y };
1488     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1489     MCTF_CHECK_CM_ERR(res, res);
1490     //scene numbers
1491     mfxU8quad scene_num_gpu = { (mfxU8)scene_numbers[0], (mfxU8)scene_numbers[1], (mfxU8)scene_numbers[2], 2 };
1492     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(scene_num_gpu), &scene_num_gpu);
1493     MCTF_CHECK_CM_ERR(res, res);
1494     return res;
1495 }
1496 
MCTF_SET_KERNELMc2rDen(mfxU16 start_x,mfxU16 start_y)1497 mfxI32 CMC::MCTF_SET_KERNELMc2rDen(
1498     mfxU16 start_x,
1499     mfxU16 start_y
1500 )
1501 {
1502     argIdx = 0;
1503     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1504     MCTF_CHECK_CM_ERR(res, res);
1505     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*QfIn[0].fIdx), QfIn[0].fIdx);
1506     MCTF_CHECK_CM_ERR(res, res);
1507     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*idxMv_1), idxMv_1);
1508     MCTF_CHECK_CM_ERR(res, res);
1509     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*QfIn[2].fIdx), QfIn[2].fIdx);
1510     MCTF_CHECK_CM_ERR(res, res);
1511     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*idxMv_2), idxMv_2);
1512     MCTF_CHECK_CM_ERR(res, res);
1513     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*QfIn[1].fIdx), QfIn[1].fIdx);
1514     MCTF_CHECK_CM_ERR(res, res);
1515     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*idxMco2), idxMco2);
1516     MCTF_CHECK_CM_ERR(res, res);
1517     // set start mb
1518     mfxU16Pair start_xy = { start_x, start_y };
1519     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1520     MCTF_CHECK_CM_ERR(res, res);
1521     //scene numbers
1522     mfxU8quad scene_num_gpu = { (mfxU8)scene_numbers[0], (mfxU8)scene_numbers[1], (mfxU8)scene_numbers[2], 2 };
1523     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(scene_num_gpu), &scene_num_gpu);
1524     MCTF_CHECK_CM_ERR(res, res);
1525     return res;
1526 }
1527 
MCTF_SET_KERNELMc4r(mfxU16 start_x,mfxU16 start_y)1528 mfxI32 CMC::MCTF_SET_KERNELMc4r(
1529     mfxU16 start_x,
1530     mfxU16 start_y
1531 )
1532 {
1533     argIdx = 0;
1534     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1535     MCTF_CHECK_CM_ERR(res, res);
1536     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxRef1), idxRef1);
1537     MCTF_CHECK_CM_ERR(res, res);
1538     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxMv_1), idxMv_1);
1539     MCTF_CHECK_CM_ERR(res, res);
1540     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxRef2), idxRef2);
1541     MCTF_CHECK_CM_ERR(res, res);
1542     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxMv_2), idxMv_2);
1543     MCTF_CHECK_CM_ERR(res, res);
1544     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxRef3), idxRef3);
1545     MCTF_CHECK_CM_ERR(res, res);
1546     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxMv_3), idxMv_3);
1547     MCTF_CHECK_CM_ERR(res, res);
1548     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxRef4), idxRef4);
1549     MCTF_CHECK_CM_ERR(res, res);
1550     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxMv_4), idxMv_4);
1551     MCTF_CHECK_CM_ERR(res, res);
1552     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxSrc), idxSrc);
1553     MCTF_CHECK_CM_ERR(res, res);
1554     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxMco), idxMco);
1555     MCTF_CHECK_CM_ERR(res, res);
1556     // set start mb
1557     mfxU16Pair start_xy = { start_x, start_y };
1558     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1559     MCTF_CHECK_CM_ERR(res, res);
1560     return res;
1561 }
1562 
MCTF_SET_KERNELMc4r(mfxU16 start_x,mfxU16 start_y,SurfaceIndex * multiIndex)1563 mfxI32 CMC::MCTF_SET_KERNELMc4r(
1564     mfxU16         start_x,
1565     mfxU16         start_y,
1566     SurfaceIndex * multiIndex
1567 )
1568 {
1569     argIdx = 0;
1570     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1571     MCTF_CHECK_CM_ERR(res, res);
1572     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*multiIndex), multiIndex);
1573     MCTF_CHECK_CM_ERR(res, res);
1574     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxSrc), idxSrc);
1575     MCTF_CHECK_CM_ERR(res, res);
1576     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxMco), idxMco);
1577     MCTF_CHECK_CM_ERR(res, res);
1578     // set start mb
1579     mfxU16Pair start_xy = { start_x, start_y };
1580     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1581     MCTF_CHECK_CM_ERR(res, res);
1582     return res;
1583 }
1584 
MCTF_SET_KERNELMcMerge(mfxU16 start_x,mfxU16 start_y)1585 mfxI32 CMC::MCTF_SET_KERNELMcMerge(
1586     mfxU16 start_x,
1587     mfxU16 start_y
1588 )
1589 {
1590     argIdx = 0;
1591     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxMco), idxMco);
1592     MCTF_CHECK_CM_ERR(res, res);
1593     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(*idxMco2), idxMco2);
1594     MCTF_CHECK_CM_ERR(res, res);
1595     // set start mb
1596     mfxU16Pair start_xy = { start_x, start_y };
1597     res = kernelMc4r->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1598     MCTF_CHECK_CM_ERR(res, res);
1599     return res;
1600 }
1601 
MCTF_SET_KERNELMc4r(mfxU16 start_x,mfxU16 start_y,mfxU8 runType)1602 mfxI32 CMC::MCTF_SET_KERNELMc4r(
1603     mfxU16 start_x,
1604     mfxU16 start_y,
1605     mfxU8  runType
1606 )
1607 {
1608     argIdx = 0;
1609     mfxU8
1610         currentFrame = 2,
1611         pastRef = 1,
1612         futureRef = 3;
1613     SurfaceIndex
1614         **mcOut = &idxMco,
1615         **pastMv = &idxMv_1,
1616         **futureMv = &idxMv_2;
1617 
1618     if (runType == DEN_FAR_RUN)
1619     {
1620         pastRef = 0;
1621         futureRef = 4;
1622         mcOut = &idxMco2;
1623         pastMv = &idxMv_3;
1624         futureMv = &idxMv_4;
1625     }
1626 
1627     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1628     MCTF_CHECK_CM_ERR(res, res);
1629     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*QfIn[pastRef].fIdx), QfIn[pastRef].fIdx);
1630     MCTF_CHECK_CM_ERR(res, res);
1631     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(**pastMv), *pastMv);
1632     MCTF_CHECK_CM_ERR(res, res);
1633     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*QfIn[futureRef].fIdx), QfIn[futureRef].fIdx);
1634     MCTF_CHECK_CM_ERR(res, res);
1635     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(**futureMv), *futureMv);
1636     MCTF_CHECK_CM_ERR(res, res);
1637     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(*QfIn[currentFrame].fIdx), QfIn[currentFrame].fIdx);
1638     MCTF_CHECK_CM_ERR(res, res);
1639     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(**mcOut), *mcOut);
1640     MCTF_CHECK_CM_ERR(res, res);
1641     // set start mb
1642     mfxU16Pair start_xy = { start_x, start_y };
1643     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1644     MCTF_CHECK_CM_ERR(res, res);
1645     //scene numbers
1646     mfxU8quad scene_num_gpu = { (mfxU8)scene_numbers[pastRef], (mfxU8)scene_numbers[currentFrame], (mfxU8)scene_numbers[futureRef], 2 };
1647     res = kernelMc2r->SetKernelArg(argIdx++, sizeof(scene_num_gpu), &scene_num_gpu);
1648     MCTF_CHECK_CM_ERR(res, res);
1649     return res;
1650 }
1651 
MCTF_SET_KERNEL_Noise(mfxU16 srcNum,mfxU16 start_x,mfxU16 start_y)1652 mfxI32 CMC::MCTF_SET_KERNEL_Noise(
1653     mfxU16 srcNum,
1654     mfxU16 start_x,
1655     mfxU16 start_y
1656 )
1657 {
1658     argIdx = 0;
1659     res = kernelNoise->SetKernelArg(argIdx++, sizeof(*QfIn[srcNum].fIdx), QfIn[srcNum].fIdx);
1660     MCTF_CHECK_CM_ERR(res, res);
1661     res = kernelNoise->SetKernelArg(argIdx++, sizeof(*idxNoiseAnalysis), idxNoiseAnalysis);
1662     MCTF_CHECK_CM_ERR(res, res);
1663     // set start mb
1664     mfxU16Pair start_xy = { start_x, start_y };
1665     res = kernelNoise->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1666     MCTF_CHECK_CM_ERR(res, res);
1667     return res;
1668 }
1669 
MCTF_SET_KERNELDe(mfxU16 srcNum,mfxU16 start_x,mfxU16 start_y)1670 mfxI32 CMC::MCTF_SET_KERNELDe(
1671     mfxU16 srcNum,
1672     mfxU16 start_x,
1673     mfxU16 start_y
1674 )
1675 {
1676     argIdx = 0;
1677     res = kernelMcDen->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1678     MCTF_CHECK_CM_ERR(res, res);
1679     res = kernelMcDen->SetKernelArg(argIdx++, sizeof(*QfIn[srcNum].fIdx), QfIn[srcNum].fIdx);
1680     MCTF_CHECK_CM_ERR(res, res);
1681     res = kernelMcDen->SetKernelArg(argIdx++, sizeof(*idxMco), idxMco);
1682     MCTF_CHECK_CM_ERR(res, res);
1683     // set start mb
1684     mfxU16Pair start_xy = { start_x, start_y };
1685     res = kernelMcDen->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1686     MCTF_CHECK_CM_ERR(res, res);
1687     return res;
1688 }
1689 
MCTF_SET_KERNELDe(mfxU16 start_x,mfxU16 start_y)1690 mfxI32 CMC::MCTF_SET_KERNELDe(
1691     mfxU16 start_x,
1692     mfxU16 start_y
1693 )
1694 {
1695     argIdx = 0;
1696     res = kernelMcDen->SetKernelArg(argIdx++, sizeof(*idxCtrl), idxCtrl);
1697     MCTF_CHECK_CM_ERR(res, res);
1698     res = kernelMcDen->SetKernelArg(argIdx++, sizeof(*idxMco), idxMco);
1699     MCTF_CHECK_CM_ERR(res, res);
1700     res = kernelMcDen->SetKernelArg(argIdx++, sizeof(*idxMco), idxMco);
1701     MCTF_CHECK_CM_ERR(res, res);
1702     // set start mb
1703     mfxU16Pair start_xy = { start_x, start_y };
1704     res = kernelMcDen->SetKernelArg(argIdx++, sizeof(start_xy), &start_xy);
1705     MCTF_CHECK_CM_ERR(res, res);
1706     return res;
1707 }
1708 
MCTF_Enqueue(CmTask * taskInt,CmEvent * & eInt,const CmThreadSpace * tSInt)1709 mfxI32 CMC::MCTF_Enqueue(
1710     CmTask* taskInt,
1711     CmEvent* & eInt,
1712     const CmThreadSpace* tSInt
1713 )
1714 {
1715     mfxI32
1716         ret = CM_FAILURE;
1717         switch (mctf_HWType){
1718         case MFX_HW_ICL:
1719             ret = queue->EnqueueFast(taskInt, eInt, tSInt);
1720             break;
1721         default:
1722             ret = queue->Enqueue(taskInt, eInt, tSInt);
1723         }
1724     return ret;
1725 }
1726 
MCTF_RUN_TASK_NA(CmKernel * kernel,bool reset,mfxU16 widthTs,mfxU16 heightTs)1727 mfxI32 CMC::MCTF_RUN_TASK_NA(
1728     CmKernel * kernel,
1729     bool       reset,
1730     mfxU16     widthTs,
1731     mfxU16     heightTs
1732 )
1733 {
1734     res = kernel->SetThreadCount(widthTs * heightTs);
1735     MCTF_CHECK_CM_ERR(res, res);
1736     res = device->CreateThreadSpace(widthTs, heightTs, threadSpace);
1737     MCTF_CHECK_CM_ERR(res, res);
1738     res = kernel->AssociateThreadSpace(threadSpace);
1739     MCTF_CHECK_CM_ERR(res, res);
1740 
1741     if (reset)
1742     {
1743         res = task->Reset();
1744         MCTF_CHECK_CM_ERR(res, res);
1745     }
1746     else
1747     {
1748         res = device->CreateTask(task);
1749         MCTF_CHECK_CM_ERR(res, res);
1750     }
1751     res = task->AddKernel(kernel);
1752     MCTF_CHECK_CM_ERR(res, res);
1753     res = MCTF_Enqueue(task, e);
1754     MCTF_CHECK_CM_ERR(res, res);
1755     return res;
1756 }
1757 
MCTF_RUN_TASK(CmKernel * kernel,bool reset)1758 mfxI32 CMC::MCTF_RUN_TASK(
1759     CmKernel * kernel,
1760     bool       reset
1761 )
1762 {
1763     res = kernel->SetThreadCount(tsWidth * tsHeight);
1764     MCTF_CHECK_CM_ERR(res, res);
1765     res = device->CreateThreadSpace(tsWidth, tsHeight, threadSpace);
1766     MCTF_CHECK_CM_ERR(res, res);
1767     res = kernel->AssociateThreadSpace(threadSpace);
1768     MCTF_CHECK_CM_ERR(res, res);
1769 
1770     if (reset)
1771     {
1772         res = task->Reset();
1773         MCTF_CHECK_CM_ERR(res, res);
1774     }
1775     else
1776     {
1777         res = device->CreateTask(task);
1778         MCTF_CHECK_CM_ERR(res, res);
1779     }
1780     res = task->AddKernel(kernel);
1781     MCTF_CHECK_CM_ERR(res, res);
1782     res = MCTF_Enqueue(task, e);
1783     MCTF_CHECK_CM_ERR(res, res);
1784     return res;
1785 }
1786 
MCTF_RUN_DOUBLE_TASK(CmKernel * meKernel,CmKernel * mcKernel,bool reset)1787 mfxI32 CMC::MCTF_RUN_DOUBLE_TASK(
1788     CmKernel * meKernel,
1789     CmKernel * mcKernel,
1790     bool       reset
1791 )
1792 {
1793     res = meKernel->SetThreadCount(tsWidth * tsHeight);
1794     MCTF_CHECK_CM_ERR(res, res);
1795     res = device->CreateThreadSpace(tsWidth, tsHeight, threadSpace2);
1796     MCTF_CHECK_CM_ERR(res, res);
1797     res = meKernel->AssociateThreadSpace(threadSpace2);
1798     MCTF_CHECK_CM_ERR(res, res);
1799 
1800     res = mcKernel->SetThreadCount(tsWidthMC * tsHeightMC);
1801     MCTF_CHECK_CM_ERR(res, res);
1802     res = device->CreateThreadSpace(tsWidthMC, tsHeightMC, threadSpaceMC);
1803     MCTF_CHECK_CM_ERR(res, res);
1804     res = mcKernel->AssociateThreadSpace(threadSpaceMC);
1805     MCTF_CHECK_CM_ERR(res, res);
1806 
1807     if (reset)
1808     {
1809         res = task->Reset();
1810         MCTF_CHECK_CM_ERR(res, res);
1811     }
1812     else
1813     {
1814         res = device->CreateTask(task);
1815         MCTF_CHECK_CM_ERR(res, res);
1816     }
1817     res = task->AddKernel(meKernel);
1818     MCTF_CHECK_CM_ERR(res, res);
1819     res = task->AddSync();
1820     MCTF_CHECK_CM_ERR(res, res);
1821     res = task->AddKernel(mcKernel);
1822     MCTF_CHECK_CM_ERR(res, res);
1823     res = MCTF_Enqueue(task, e);
1824     MCTF_CHECK_CM_ERR(res, res);
1825     return res;
1826 }
1827 
MCTF_RUN_MCTASK(CmKernel * kernel,bool reset)1828 mfxI32 CMC::MCTF_RUN_MCTASK(
1829     CmKernel * kernel,
1830     bool       reset
1831 )
1832 {
1833     res = kernel->SetThreadCount(tsWidthMC * tsHeightMC);
1834     MCTF_CHECK_CM_ERR(res, res);
1835     res = device->CreateThreadSpace(tsWidthMC, tsHeightMC, threadSpaceMC2);
1836     MCTF_CHECK_CM_ERR(res, res);
1837 
1838     if (reset)
1839     {
1840         res = task->Reset();
1841         MCTF_CHECK_CM_ERR(res, res);
1842     }
1843     else
1844     {
1845         res = device->CreateTask(task);
1846         MCTF_CHECK_CM_ERR(res, res);
1847     }
1848     res = task->AddKernel(kernel);
1849     MCTF_CHECK_CM_ERR(res, res);
1850     res = MCTF_Enqueue(task, e, threadSpaceMC2);
1851     MCTF_CHECK_CM_ERR(res, res);
1852     return res;
1853 }
1854 
MCTF_RUN_TASK(CmKernel * kernel,bool reset,CmThreadSpace * tS)1855 mfxI32 CMC::MCTF_RUN_TASK(
1856     CmKernel      * kernel,
1857     bool            reset,
1858     CmThreadSpace * tS
1859 )
1860 {
1861     res = kernel->SetThreadCount(tsWidth * tsHeight);
1862     MCTF_CHECK_CM_ERR(res, res);
1863     res = device->CreateThreadSpace(tsWidth, tsHeight, tS);
1864     MCTF_CHECK_CM_ERR(res, res);
1865     if (reset)
1866     {
1867         res = task->Reset();
1868         MCTF_CHECK_CM_ERR(res, res);
1869     }
1870     else
1871     {
1872         res = device->CreateTask(task);
1873         MCTF_CHECK_CM_ERR(res, res);
1874     }
1875     res = task->AddKernel(kernel);
1876     MCTF_CHECK_CM_ERR(res, res);
1877     res = MCTF_Enqueue(task, e, tS);
1878     MCTF_CHECK_CM_ERR(res, res);
1879     res = device->DestroyThreadSpace(tS);
1880     return res;
1881 }
1882 
SetOverlapOp()1883 mfxU8 CMC::SetOverlapOp()
1884 {
1885     mfxU8 blSize = 0;
1886     switch (overlap_Motion)
1887     {
1888     case MFX_CODINGOPTION_ON:
1889     {
1890         blSize = VMEBLSIZE / 2;
1891         tsHeight = (DIVUP(p_ctrl->CropH, VMEBLSIZE) * 2) - 1;//Motion Estimation of any block size is performed in 16x16 units
1892         tsWidthFull = (DIVUP(p_ctrl->CropW, VMEBLSIZE) * 2) - 1;
1893     }
1894     break;
1895     case MFX_CODINGOPTION_UNKNOWN:
1896     case MFX_CODINGOPTION_OFF:
1897     {
1898         blSize = VMEBLSIZE;
1899         tsHeight = DIVUP(p_ctrl->CropH, VMEBLSIZE);//Motion Estimation of any block size is performed in 16x16 units
1900         tsWidthFull = DIVUP(p_ctrl->CropW, VMEBLSIZE);
1901     }
1902     break;
1903     default:
1904         throw CMCRuntimeError();
1905     }
1906     tsWidth = tsWidthFull;
1907     return blSize;
1908 }
1909 
SetOverlapOp_half()1910 mfxU8 CMC::SetOverlapOp_half()
1911 {
1912     mfxU8 blSize = 0;
1913     switch (overlap_Motion)
1914     {
1915     case MFX_CODINGOPTION_ON:
1916     {
1917         blSize = VMEBLSIZE / 2;
1918         tsHeight = DIVUP(p_ctrl->CropH, VMEBLSIZE) - 1;//Motion Estimation of any block size is performed in 16x16 units
1919         tsWidthFull = (DIVUP(p_ctrl->CropW, VMEBLSIZE) * 2) - 1;
1920     }
1921     break;
1922 
1923     case MFX_CODINGOPTION_OFF:
1924     case MFX_CODINGOPTION_UNKNOWN:
1925     {
1926         blSize = VMEBLSIZE;
1927         tsHeight = DIVUP(p_ctrl->CropH, VMEBLSIZE) / 2;//Motion Estimation of any block size is performed in 16x16 units
1928         tsWidthFull = DIVUP(p_ctrl->CropW, VMEBLSIZE);
1929     }
1930     break;
1931     default:
1932         throw CMCRuntimeError();
1933     }
1934     tsWidth = tsWidthFull;
1935     return blSize;
1936 }
1937 
MCTF_RUN_ME(SurfaceIndex * GenxRefs,SurfaceIndex * idxMV)1938 mfxI32 CMC::MCTF_RUN_ME(
1939     SurfaceIndex * GenxRefs,
1940     SurfaceIndex * idxMV
1941 )
1942 {
1943     time = 0;
1944 
1945     mfxU8
1946         blSize = SetOverlapOp();
1947     res = MCTF_SET_KERNELMe(GenxRefs, idxMV, DIVUP(p_ctrl->CropX, blSize) , DIVUP(p_ctrl->CropY, blSize), blSize);
1948     MCTF_CHECK_CM_ERR(res, res);
1949     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
1950         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
1951 
1952     threadSpace = 0;
1953     res = MCTF_RUN_TASK(kernelMe, task != 0);
1954     MCTF_CHECK_CM_ERR(res, res);
1955 
1956     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
1957     {
1958         mfxU16 start_mbX = tsWidth;
1959         tsWidth = tsWidthFull - tsWidth;
1960         res = MCTF_SET_KERNELMe(GenxRefs, idxMV, start_mbX, DIVUP(p_ctrl->CropY, blSize), blSize);
1961         MCTF_CHECK_CM_ERR(res, res);
1962         // the rest of frame TS
1963         res = MCTF_RUN_TASK(kernelMe, task != 0);
1964         MCTF_CHECK_CM_ERR(res, res);
1965     }
1966     return res;
1967 }
1968 
MCTF_RUN_ME(SurfaceIndex * GenxRefs,SurfaceIndex * GenxRefs2,SurfaceIndex * idxMV,SurfaceIndex * idxMV2,char forwardRefDist,char backwardRefDist)1969 mfxI32 CMC::MCTF_RUN_ME(
1970     SurfaceIndex * GenxRefs,
1971     SurfaceIndex * GenxRefs2,
1972     SurfaceIndex * idxMV,
1973     SurfaceIndex * idxMV2,
1974     char           forwardRefDist,
1975     char           backwardRefDist
1976 )
1977 {
1978     mfxU8
1979         blSize = SetOverlapOp();
1980     res = MCTF_SET_KERNELMeBi(GenxRefs, GenxRefs2, idxMV, idxMV2, 0, 0, blSize, forwardRefDist, backwardRefDist);
1981     MCTF_CHECK_CM_ERR(res, res);
1982     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
1983         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
1984 
1985     threadSpace = 0;
1986     res = MCTF_RUN_TASK(kernelMeB, task != 0);
1987     MCTF_CHECK_CM_ERR(res, res);
1988 
1989     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
1990     {
1991         mfxU16
1992             start_mbX = tsWidth;
1993         tsWidth = tsWidthFull - tsWidth;
1994         res = MCTF_SET_KERNELMeBi(GenxRefs, GenxRefs2, idxMV, idxMV2, start_mbX, 0, blSize, forwardRefDist, backwardRefDist);
1995 
1996         MCTF_CHECK_CM_ERR(res, res);
1997         // the rest of frame TS
1998         res = MCTF_RUN_TASK(kernelMeB, task != 0);
1999         MCTF_CHECK_CM_ERR(res, res);
2000     }
2001     return res;
2002 }
2003 
MCTF_RUN_ME_MC_HE(SurfaceIndex * GenxRefs,SurfaceIndex * GenxRefs2,SurfaceIndex * idxMV,SurfaceIndex * idxMV2,mfxI8 forwardRefDist,mfxI8 backwardRefDist,mfxU8 mcSufIndex)2004 mfxI32 CMC::MCTF_RUN_ME_MC_HE(
2005     SurfaceIndex* GenxRefs,
2006     SurfaceIndex* GenxRefs2,
2007     SurfaceIndex* idxMV,
2008     SurfaceIndex* idxMV2,
2009     mfxI8         forwardRefDist,
2010     mfxI8         backwardRefDist,
2011     mfxU8         mcSufIndex
2012 )
2013 {
2014     p_ctrl->sTh = MCTF_CHROMAOFF;
2015     p_ctrl->th = QfIn[1].filterStrength * 50;
2016     res = ctrlBuf->WriteSurface((const mfxU8 *)p_ctrl.get(), NULL, sizeof(MeControlSmall));
2017     MCTF_CHECK_CM_ERR(res, res);
2018     time = 0;
2019 
2020     mfxU8
2021         blSize = SetOverlapOp_half();
2022     mfxU16
2023         multiplier = 2;
2024     UINT64
2025         executionTime = 0;
2026     tsHeightMC = (DIVUP(p_ctrl->height, blsize) * multiplier);
2027     tsWidthFullMC = (DIVUP(p_ctrl->width, blsize) * multiplier);
2028     tsWidthMC = tsWidthFullMC;
2029 
2030     res = MCTF_SET_KERNELMeBiMRE(GenxRefs, GenxRefs2, idxMV, idxMV2, 0, 0, blSize, forwardRefDist, backwardRefDist);
2031     MCTF_CHECK_CM_ERR(res, res);
2032     res = MCTF_SET_KERNELMeBiMRE2(GenxRefs, GenxRefs2, idxMV, idxMV2, 0, tsHeight, blSize, forwardRefDist, backwardRefDist);
2033     MCTF_CHECK_CM_ERR(res, res);
2034 
2035     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MO)
2036     {
2037         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
2038     }
2039 
2040     if (tsWidthFullMC > CM_MAX_THREADSPACE_WIDTH_FOR_MO)
2041     {
2042         tsWidthMC = (tsWidthFullMC >> 1) & ~1;  // must be even for 32x32 blocks
2043     }
2044 
2045     threadSpace   = 0;
2046     threadSpace2  = 0;
2047     threadSpaceMC = 0;
2048 
2049     res = kernelMeB->SetThreadCount(tsWidth * tsHeight);
2050     MCTF_CHECK_CM_ERR(res, res);
2051     res = device->CreateThreadSpace(tsWidth, tsHeight, threadSpace);
2052     MCTF_CHECK_CM_ERR(res, res);
2053     res = kernelMeB->AssociateThreadSpace(threadSpace);
2054     MCTF_CHECK_CM_ERR(res, res);
2055 
2056     res = kernelMeB2->SetThreadCount(tsWidth * tsHeight);
2057     MCTF_CHECK_CM_ERR(res, res);
2058     res = device->CreateThreadSpace(tsWidth, tsHeight, threadSpace2);
2059     MCTF_CHECK_CM_ERR(res, res);
2060     res = kernelMeB2->AssociateThreadSpace(threadSpace2);
2061     MCTF_CHECK_CM_ERR(res, res);
2062 
2063     res = kernelMc2r->SetThreadCount(tsWidthMC * tsHeightMC);
2064     MCTF_CHECK_CM_ERR(res, res);
2065     res = device->CreateThreadSpace(tsWidthMC, tsHeightMC, threadSpaceMC);
2066     MCTF_CHECK_CM_ERR(res, res);
2067     res = kernelMc2r->AssociateThreadSpace(threadSpaceMC);
2068     MCTF_CHECK_CM_ERR(res, res);
2069 
2070     if (task)
2071         res = task->Reset();
2072     else
2073         res = device->CreateTask(task);
2074     MCTF_CHECK_CM_ERR(res, res);
2075 
2076     res = task->AddKernel(kernelMeB);
2077     MCTF_CHECK_CM_ERR(res, res);
2078     if (pMCTF_NOA_func && p_ctrl->th == MCTFADAPTIVEVAL)
2079     {
2080         res = MCTF_Enqueue(task, e);
2081         MCTF_CHECK_CM_ERR(res, res);
2082         res = e->WaitForTaskFinished();
2083         MCTF_CHECK_CM_ERR(res, res);
2084 
2085         res = device->DestroyThreadSpace(threadSpace);
2086         MCTF_CHECK_CM_ERR(res, res);
2087 
2088         e->GetExecutionTime(executionTime);
2089         exeTime += executionTime / 1000;
2090         exeTimeT += executionTime / 1000;
2091 
2092         (this->*(pMCTF_NOA_func))(m_adaptControl);
2093         if (QfIn[1].filterStrength == 0)
2094         {
2095             MctfState = AMCTF_READY;
2096             return CM_SUCCESS;
2097         }
2098 
2099         if (mcSufIndex == 0)
2100             res = MCTF_SET_KERNELMc2r(0, 0);
2101         else if (mcSufIndex == 1)
2102             res = MCTF_SET_KERNELMc4r(0, 0, DEN_CLOSE_RUN);
2103         else
2104             res = MCTF_SET_KERNELMc4r(0, 0, DEN_FAR_RUN);
2105         MCTF_CHECK_CM_ERR(res, res);
2106 
2107         res = task->Reset();
2108         MCTF_CHECK_CM_ERR(res, res);
2109 
2110     }
2111     else {
2112         res = task->AddSync();
2113         if (mcSufIndex == 0)
2114             res = MCTF_SET_KERNELMc2r(0, 0);
2115         else if (mcSufIndex == 1)
2116             res = MCTF_SET_KERNELMc4r(0, 0, DEN_CLOSE_RUN);
2117         else
2118             res = MCTF_SET_KERNELMc4r(0, 0, DEN_FAR_RUN);
2119         MCTF_CHECK_CM_ERR(res, res);
2120     }
2121 
2122     res = task->AddKernel(kernelMeB2);
2123     MCTF_CHECK_CM_ERR(res, res);
2124     res = task->AddSync();
2125     MCTF_CHECK_CM_ERR(res, res);
2126     res = task->AddKernel(kernelMc2r);
2127     MCTF_CHECK_CM_ERR(res, res);
2128 
2129     res = MCTF_Enqueue(task, e);
2130     MCTF_CHECK_CM_ERR(res, res);
2131     MctfState = AMCTF_READY;
2132     res = e->WaitForTaskFinished();
2133     MCTF_CHECK_CM_ERR(res, res);
2134     e->GetExecutionTime(executionTime);
2135     exeTime += executionTime / 1000;
2136 
2137     if (!pMCTF_NOA_func) {
2138         res = device->DestroyThreadSpace(threadSpace);
2139         MCTF_CHECK_CM_ERR(res, res);
2140     }
2141 
2142     res = device->DestroyThreadSpace(threadSpace2);
2143     MCTF_CHECK_CM_ERR(res, res);
2144     res = device->DestroyThreadSpace(threadSpaceMC);
2145     MCTF_CHECK_CM_ERR(res, res);
2146 
2147 
2148     res = device->DestroyVmeSurfaceG7_5(GenxRefs);
2149     MCTF_CHECK_CM_ERR(res, res);
2150     res = device->DestroyVmeSurfaceG7_5(GenxRefs2);
2151     MCTF_CHECK_CM_ERR(res, res);
2152     res = device->DestroyTask(task);
2153     MCTF_CHECK_CM_ERR(res, res);
2154     MctfState = AMCTF_READY;
2155     task = 0;
2156     return res;
2157 }
2158 
MCTF_RUN_ME_MC_H(SurfaceIndex * GenxRefs,SurfaceIndex * GenxRefs2,SurfaceIndex * idxMV,SurfaceIndex * idxMV2,mfxI8 forwardRefDist,mfxI8 backwardRefDist,mfxU8 mcSufIndex)2159 mfxI32 CMC::MCTF_RUN_ME_MC_H(
2160     SurfaceIndex * GenxRefs,
2161     SurfaceIndex * GenxRefs2,
2162     SurfaceIndex * idxMV,
2163     SurfaceIndex * idxMV2,
2164     mfxI8          forwardRefDist,
2165     mfxI8           backwardRefDist,
2166     mfxU8          mcSufIndex
2167 )
2168 {
2169     UINT64 executionTime;
2170     mfxU8
2171         blSize = SetOverlapOp_half();
2172     res = MCTF_SET_KERNELMeBi(GenxRefs, GenxRefs2, idxMV, idxMV2, DIVUP(p_ctrl->CropX, blSize), DIVUP(p_ctrl->CropY, blSize), blSize, forwardRefDist, backwardRefDist);
2173 
2174     MCTF_CHECK_CM_ERR(res, res);
2175 
2176     threadSpace = 0;
2177 
2178     res = MCTF_RUN_TASK(kernelMeB, task != 0);
2179     res = e->WaitForTaskFinished();
2180     MCTF_CHECK_CM_ERR(res, res);
2181     e->GetExecutionTime(executionTime);
2182     exeTime += executionTime / 1000;
2183 
2184     mfxU16 multiplier = 2;
2185     tsHeightMC = (DIVUP(p_ctrl->CropH, blsize) * multiplier);
2186     tsWidthFullMC = (DIVUP(p_ctrl->CropW, blsize) * multiplier);
2187     tsWidthMC = tsWidthFullMC;
2188 
2189     if (pMCTF_NOA_func)
2190     {
2191         res = MCTF_Enqueue(task, e);
2192         MCTF_CHECK_CM_ERR(res, res);
2193         res = e->WaitForTaskFinished();
2194         MCTF_CHECK_CM_ERR(res, res);
2195         res = device->DestroyThreadSpace(threadSpace);
2196         MCTF_CHECK_CM_ERR(res, res);
2197 
2198         res = device->DestroyTask(task);
2199         MCTF_CHECK_CM_ERR(res, res);
2200         e->GetExecutionTime(executionTime);
2201         exeTime += executionTime / 1000;
2202         res = queue->DestroyEvent(e);
2203         MCTF_CHECK_CM_ERR(res, res);
2204         task = 0;
2205         e = 0;
2206         (this->*(pMCTF_NOA_func))(m_adaptControl);
2207     }
2208     else
2209         res = task->AddSync();
2210     res = MCTF_SET_KERNELMeBi(GenxRefs, GenxRefs2, idxMV, idxMV2, DIVUP(p_ctrl->CropX, blsize), tsHeight, blSize, forwardRefDist, backwardRefDist);
2211 
2212     MCTF_CHECK_CM_ERR(res, res);
2213     if (mcSufIndex == 0)
2214         res = MCTF_SET_KERNELMc2r(DIVUP(p_ctrl->CropX, blSize) * 2, DIVUP(p_ctrl->CropY, blSize) * 2);
2215     else if (mcSufIndex == 1)
2216         res = MCTF_SET_KERNELMc4r(DIVUP(p_ctrl->CropX, blSize) * 2, DIVUP(p_ctrl->CropY, blSize) * 2, DEN_CLOSE_RUN);
2217     else
2218         res = MCTF_SET_KERNELMc4r(DIVUP(p_ctrl->CropX, blSize) * 2, DIVUP(p_ctrl->CropY, blSize) * 2, DEN_FAR_RUN);
2219     MCTF_CHECK_CM_ERR(res, res);
2220 
2221     threadSpace2 = 0;
2222     threadSpaceMC = 0;
2223 
2224     MCTF_RUN_DOUBLE_TASK(kernelMeB, kernelMc2r, task != 0);
2225     MCTF_CHECK_CM_ERR(res, res);
2226     res = e->WaitForTaskFinished();
2227     MCTF_CHECK_CM_ERR(res, res);
2228     e->GetExecutionTime(executionTime);
2229     exeTime += executionTime / 1000;
2230     res = device->DestroyThreadSpace(threadSpace2);
2231     MCTF_CHECK_CM_ERR(res, res);
2232     res = device->DestroyThreadSpace(threadSpaceMC);
2233     MCTF_CHECK_CM_ERR(res, res);
2234     if (threadSpace)
2235     {
2236         res = device->DestroyThreadSpace(threadSpace);
2237         MCTF_CHECK_CM_ERR(res, res);
2238     }
2239 
2240     res = device->DestroyVmeSurfaceG7_5(GenxRefs);
2241     MCTF_CHECK_CM_ERR(res, res);
2242     res = device->DestroyVmeSurfaceG7_5(GenxRefs2);
2243     MCTF_CHECK_CM_ERR(res, res);
2244     res = device->DestroyTask(task);
2245     MCTF_CHECK_CM_ERR(res, res);
2246     res = queue->DestroyEvent(e);
2247     task = 0;
2248     e = 0;
2249     return res;
2250 }
2251 
GET_DISTDATA()2252 void CMC::GET_DISTDATA()
2253 {
2254     for (int y = 0; y < ov_height_bl; y++)
2255     {
2256         mfxU32 * src = reinterpret_cast<mfxU32*>(reinterpret_cast<mfxU8*>(distSys) + y * surfPitch);
2257         std::copy(src, src + ov_width_bl, &distRef[y * ov_width_bl]);
2258     }
2259 }
2260 
GET_DISTDATA_H()2261 void CMC::GET_DISTDATA_H()
2262 {
2263     for (int y = 0; y < ov_height_bl / 2; y++)
2264     {
2265         mfxU32 * src = reinterpret_cast<mfxU32*>(reinterpret_cast<mfxU8*>(distSys) + y * surfPitch);
2266         std::copy(src, src + ov_width_bl, &distRef[y * ov_width_bl]);
2267     }
2268 }
2269 
GET_NOISEDATA()2270 void CMC::GET_NOISEDATA()
2271 {
2272     for (int y = 0; y < DIVUP(p_ctrl->CropH, 16); y++)
2273     {
2274         spatialNoiseAnalysis * src = reinterpret_cast<spatialNoiseAnalysis*>(reinterpret_cast<mfxU8*>(noiseAnalysisSys) + y * surfNoisePitch);
2275         std::copy(src, src + DIVUP(p_ctrl->CropW, 16), &var_sc[y * DIVUP(p_ctrl->CropW, 16)]);
2276     }
2277 }
2278 
GET_TOTAL_SAD()2279 mfxF64 CMC::GET_TOTAL_SAD()
2280 {
2281     mfxF64 total_sad = 0.0;
2282     // to not lose due-to normalization of floats
2283     mfxU64 uTotalSad = 0;
2284     switch (overlap_Motion)
2285     {
2286     case MFX_CODINGOPTION_ON:
2287     {//overlapped modes, need to remove extra SAD blocks and lines
2288         mfxI32
2289             pos_offset = 0;
2290         for (mfxI32 i = 0; i < ov_height_bl; i += OVERLAP_OFFSET)
2291         {
2292             pos_offset = i * ov_width_bl;
2293             for (mfxI32 j = 0; j < ov_width_bl; j += OVERLAP_OFFSET)
2294                 uTotalSad += distRef[pos_offset + j];
2295         }
2296     }
2297     break;
2298     case MFX_CODINGOPTION_UNKNOWN:
2299     case MFX_CODINGOPTION_OFF:
2300     {// Non overlapped, all blocks are needed for frame SAD calculation
2301         for (mfxU32 i = 0; i < distRef.size(); i++)
2302             uTotalSad += distRef[i];
2303     }
2304     break;
2305     default:
2306         throw CMCRuntimeError();
2307     }
2308     total_sad = mfxF64(uTotalSad);
2309     return total_sad / (p_ctrl->CropW * p_ctrl->CropH);
2310 }
2311 
CalcNoiseStrength(double NSC,double NSAD)2312 mfxU16 CalcNoiseStrength(
2313     double NSC,
2314     double NSAD
2315 )
2316 {
2317     // 10 epsilons
2318     if (std::fabs(NSC) <= 10 * std::numeric_limits<double>::epsilon()) return 0;
2319     mfxF64
2320         s,
2321         s2,
2322 
2323         c3 = -907.05,
2324         c2 =  752.69,
2325         c1 = -175.7,
2326         c0 =  14.6,
2327         d3 = -0.0000004,
2328         d2 =  0.0002,
2329         d1 = -0.0245,
2330         d0 =  4.1647,
2331 
2332         ISTC = NSAD * NSC,
2333         STC = NSAD / sqrt(NSC);
2334 
2335     s  = c3 * pow(STC, 3.0) + c2 * pow(STC, 2.0) + c1 * STC + c0;
2336     s2 = d3 * pow(ISTC, 3.0) + d2 * pow(ISTC, 2.0) + d1 * ISTC + d0;
2337     s = NMIN(s, s2) + 5;
2338     s  = NMAX(0.0, NMIN(20.0, s));
2339     return (mfxU16)(s + 0.5);
2340 }
2341 
2342 
CalcSTC(mfxF64 SCpp2,mfxF64 sadpp)2343 mfxU8 CalcSTC(mfxF64 SCpp2, mfxF64 sadpp)
2344 {
2345     mfxU8
2346         stcVal = 0;
2347     sadpp *= sadpp;
2348     // Ref was Recon (quantization err in ref biases sad)
2349     if      (sadpp < 0.03*SCpp2)  stcVal = 0; // Very-Low
2350     else if (sadpp < 0.09*SCpp2)  stcVal = 1; // Low
2351     else if (sadpp < 0.20*SCpp2)  stcVal = 2; // Low-Medium
2352     else if (sadpp < 0.36*SCpp2)  stcVal = 3; // Medium
2353     else if (sadpp < 1.44*SCpp2)  stcVal = 4; // Medium-High
2354     else if (sadpp < 3.24*SCpp2)  stcVal = 5; // High
2355     else                          stcVal = 6; // VeryHigh
2356     return stcVal;
2357 }
2358 
2359 
GetSpatioTemporalComplexityFrame(mfxU8 currentFrame)2360 void CMC::GetSpatioTemporalComplexityFrame(mfxU8 currentFrame)
2361 {
2362     mfxU8
2363         i;
2364     mfxF64
2365         SCpp2 = QfIn[currentFrame].frame_sc;
2366     static mfxF32
2367         lmt_sc2[10] = { 16.0, 81.0, 225.0, 529.0, 1024.0, 1764.0, 2809.0, 4225.0, 6084.0, (mfxF32)INT_MAX }; // lower limit of SFM(Rs,Cs) range for spatial classification
2368 
2369     for (i = 0; i < 10; i++)
2370     {
2371         if (SCpp2 < lmt_sc2[i])
2372         {
2373             QfIn[currentFrame].sc = i;
2374             break;
2375         }
2376     }
2377     QfIn[currentFrame].tc = 0;
2378     QfIn[currentFrame].stc = 0;
2379     mfxF64
2380         sadpp = QfIn[currentFrame].frame_sad;
2381     static mfxF64
2382         lmt_tc[10] = { 0.75, 1.5, 2.25, 3.00, 4.00, 5.00, 6.00, 7.50, 9.25, mfxF64(INT_MAX) };               // lower limit of AFD
2383     for (i = 0; i < 10; i++)
2384     {
2385         if (sadpp < lmt_tc[i])
2386         {
2387             QfIn[currentFrame].tc = i;
2388             break;
2389         }
2390     }
2391     QfIn[currentFrame].stc = CalcSTC(SCpp2, sadpp);
2392 }
2393 
computeQpClassFromBitRate(mfxU8 currentFrame)2394 mfxU32 CMC::computeQpClassFromBitRate(
2395     mfxU8 currentFrame
2396 )
2397 {
2398     mfxF64
2399         scL = log10(QfIn[currentFrame].sc),
2400         sadL = log10(QfIn[currentFrame].frame_sad);
2401     mfxF64
2402         d0 = sadL * scL,
2403         A, B = -0.75;
2404     d0 = pow(d0, 2.03);
2405     // 0.567701x + 1.092071
2406     A = 0.567701 * d0 + 1.092071;
2407 
2408     mfxU32         //    0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
2409         QP_CLASS[54] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
2410     mfxF64
2411         y, qs;
2412     y = A * pow(bpp, B);
2413     qs = 1.0 + log(y) / log(2.0);
2414 
2415     mfxU32
2416         QP = (mfxU32)(6.0 * qs) + 4;
2417     mfxU32
2418         QCL = (QP > 53) ? 3 : QP_CLASS[QP];
2419     return QCL;
2420 }
2421 
FilterEnable(gpuFrameData frame)2422 bool CMC::FilterEnable(
2423    gpuFrameData frame)
2424 {
2425     mfxF64
2426         noise_sad    = frame.noise_sad;
2427     mfxU32
2428         noise_count  = frame.noise_count;
2429     bool
2430         enableFilter = false;
2431     //Enabling/Disabling filter model coeficcients
2432     mfxF64
2433         s,
2434 #if defined(MFX_ENABLE_SOFT_CURVE)
2435         c2 = 165.51,
2436         c1 = -1614.4,
2437         c0 = 4085.7;
2438     s = c2 * pow(noise_sad, 2) + c1 * noise_sad + c0;
2439 #else
2440         c1 = 574.5,
2441         c0 = 2409.925;
2442     s = c1 * noise_sad + c0;
2443 #endif
2444 
2445 
2446     enableFilter = (mfxF64)noise_count > s;
2447     return enableFilter;
2448 }
2449 
noise_estimator(bool adaptControl)2450 mfxI32 CMC::noise_estimator(
2451     bool adaptControl
2452 )
2453 {
2454     mfxU8
2455         currentFrame = (number_of_References <= 2) ? 1 : 2,
2456         previousFrame = currentFrame - 1;
2457     mfxU32
2458         width = DIVUP(p_ctrl->CropW, 16),
2459         height = DIVUP(p_ctrl->CropH, 16),
2460         count = 0,
2461         row, col;
2462     mfxI16
2463         fsModVal = 0;
2464     mfxF32
2465         tvar = 281,
2466         var, SCpp, SADpp;
2467 
2468     QfIn[currentFrame].noise_var = 0.0,
2469     QfIn[currentFrame].noise_sad = 0.0,
2470     QfIn[currentFrame].noise_sc = 0.0;
2471     QfIn[currentFrame].noise_count = 1;
2472 
2473     QfIn[currentFrame].frame_sc = 0.0;
2474     QfIn[currentFrame].frame_sad = 0.0;
2475     QfIn[currentFrame].frame_Cs = 0.0;
2476     QfIn[currentFrame].frame_Rs = 0.0;
2477 
2478     GET_DISTDATA_H();
2479     res = MCTF_RUN_Noise_Analysis(currentFrame);
2480     MCTF_CHECK_CM_ERR(res, res);
2481 
2482     GET_NOISEDATA();
2483     mfxU32 distRefStride = 2 * width;
2484     switch (overlap_Motion)
2485     {
2486     case MFX_CODINGOPTION_ON:
2487     {
2488         for (row = 1; row < height / 2 - 1; row++)
2489         {
2490             for (col = 1; col < width - 1; col++)
2491             {
2492                 var = var_sc[row * width + col].var;
2493                 SCpp = var_sc[row * width + col].SCpp;
2494                 QfIn[currentFrame].frame_sc += SCpp;
2495                 SADpp = (mfxF32)(distRef[row * 2 * width * 2 + col * 2] / 256);
2496                 QfIn[currentFrame].frame_sad += SADpp;
2497                 if (var < tvar && SCpp <tvar && SCpp>1.0 && (SADpp*SADpp) <= SCpp)
2498                 {
2499                     count++;
2500                     QfIn[currentFrame].noise_var += var;
2501                     QfIn[currentFrame].noise_sc += SCpp;
2502                     QfIn[currentFrame].noise_sad += SADpp;
2503                 }
2504             }
2505         }
2506     }
2507     break;
2508     case MFX_CODINGOPTION_UNKNOWN:
2509     case MFX_CODINGOPTION_OFF:
2510     {
2511         for (row = 1; row < height / 2 - 1; row++)
2512         {
2513             for (col = 1; col < width - 1; col++)
2514             {
2515                 var = var_sc[row * width + col].var;
2516                 SCpp = var_sc[row * width + col].SCpp;
2517                 QfIn[currentFrame].frame_sc += SCpp;
2518                 // NB: division by 256 is done in integers;
2519                 // thus, for each calculation, 8 LSB are truncated
2520                 // works good; but additional efforts can be taken,
2521                 // to consider higher precision (thru calculations in integers)
2522                 // followed by wise truncating.
2523                 SADpp = (mfxF32)((distRef[row * 2 * distRefStride + col * 2] +
2524                     distRef[row * 2 * distRefStride + col * 2 + 1] +
2525                     distRef[(row * 2 + 1) * distRefStride + col * 2] +
2526                     distRef[(row * 2 + 1) * distRefStride + col * 2 + 1]) / 256);
2527                 QfIn[currentFrame].frame_sad += SADpp;
2528                 if (var < tvar && SCpp <tvar && SCpp>1.0 && (SADpp*SADpp) <= SCpp)
2529                 {
2530                     ++count;
2531                     QfIn[currentFrame].noise_var += var;
2532                     QfIn[currentFrame].noise_sc += SCpp;
2533                     QfIn[currentFrame].noise_sad += SADpp;
2534 
2535                 }
2536             }
2537         }
2538     }
2539     break;
2540     default:
2541         throw CMCRuntimeError();
2542     }
2543     QfIn[currentFrame].frame_sc /= ((height / 2 - 2) * (width - 2));
2544     QfIn[currentFrame].frame_sad /= ((height / 2 - 2) * (width - 2));
2545     if (count)
2546     {
2547         // noise_count is reserved for future use.
2548         QfIn[currentFrame].noise_count = count;
2549         QfIn[currentFrame].noise_var /= count;
2550         QfIn[currentFrame].noise_sc /= count;
2551         QfIn[currentFrame].noise_sad /= count;
2552     }
2553     mfxU16
2554         filterstrength = MCTFSTRENGTH;
2555     if (QfIn[currentFrame].scene_idx != QfIn[previousFrame].scene_idx)
2556     {
2557         filterstrength = QfIn[previousFrame].filterStrength;
2558     }
2559     else
2560     {
2561         filterstrength = CalcNoiseStrength(QfIn[currentFrame].noise_sc, QfIn[currentFrame].noise_sad);
2562         if (bitrate_Adaptation)
2563         {
2564             GetSpatioTemporalComplexityFrame(currentFrame);
2565             mfxU32
2566                 QLC = computeQpClassFromBitRate(currentFrame);
2567             if (QLC == 0)
2568                 fsModVal = QfIn[currentFrame].stc > 0.35 ? -2 : -1;
2569             else if (QLC == 1)
2570                 fsModVal = 0;
2571             else if (QLC == 2)
2572                 fsModVal = 1;
2573             else
2574                 fsModVal = 2;
2575 
2576             mfxI32 limit = filterstrength > 14 ? 13 : 20;
2577             filterstrength = mfxU16(max(0, min(limit, (mfxI16)filterstrength + fsModVal)));
2578         }
2579     }
2580     if (adaptControl)
2581     {
2582         filterstrength = FilterEnable(QfIn[currentFrame]) ? filterstrength : MCTFNOFILTER;
2583         m_doFilterFrame = !!filterstrength;
2584     }
2585     QfIn[currentFrame].filterStrength = filterstrength;
2586     gopBasedFilterStrength = filterstrength;
2587     if (adaptControl)
2588         res = SetFilterStrenght(filterstrength, MCTFNOFILTER);
2589     else
2590         res = SetFilterStrenght(filterstrength);
2591     MCTF_CHECK_CM_ERR(res, res);
2592     return res;
2593 }
2594 
MCTF_RUN_Noise_Analysis(mfxU8 srcNum)2595 mfxI32 CMC::MCTF_RUN_Noise_Analysis(mfxU8 srcNum)
2596 {
2597     res = MCTF_SET_KERNEL_Noise(srcNum, DIVUP(p_ctrl->CropX, 16), DIVUP(p_ctrl->CropY, 16));
2598     MCTF_CHECK_CM_ERR(res, res);
2599     mfxU16
2600         tsHeightNA = DIVUP(p_ctrl->CropH, 16),
2601         tsWidthFullNA = DIVUP(p_ctrl->CropW, 16),
2602         tsWidthNA = tsWidthFullNA;
2603 
2604     if (tsWidthFullNA > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2605         tsWidthNA = (tsWidthFullNA >> 1) & ~1;  // must be even for 32x32 blocks
2606 
2607     threadSpace = 0;
2608     res = MCTF_RUN_TASK_NA(kernelNoise, task != 0, tsWidthNA, tsHeightNA);
2609     MCTF_CHECK_CM_ERR(res, res);
2610 
2611     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2612     {
2613         mfxU16
2614             start_mbX = tsWidth;
2615         tsWidth = tsWidthFull - tsWidth;
2616         res = MCTF_SET_KERNEL_Noise(srcNum, start_mbX, DIVUP(p_ctrl->CropY, 16));
2617         MCTF_CHECK_CM_ERR(res, res);
2618         if (threadSpace != NULL)
2619         {
2620             res = device->DestroyThreadSpace(threadSpace);
2621             MCTF_CHECK_CM_ERR(res, res);
2622         }
2623         // the rest of frame TS
2624         res = MCTF_RUN_TASK_NA(kernelNoise, task != 0, tsWidthNA, tsHeightNA);
2625         MCTF_CHECK_CM_ERR(res, res);
2626     }
2627     res = e->WaitForTaskFinished();
2628     MCTF_CHECK_CM_ERR(res, res);
2629     device->DestroyThreadSpace(threadSpace);
2630     queue->DestroyEvent(e);
2631     e = 0;
2632     return res;
2633 }
2634 
MCTF_RUN_BLEND()2635 mfxI32 CMC::MCTF_RUN_BLEND()
2636 {
2637     mfxU16 multiplier = 2;
2638     res = MCTF_SET_KERNELMc(DIVUP(p_ctrl->CropX, blsize) * multiplier, DIVUP(p_ctrl->CropY, blsize) * multiplier, 1, 0);
2639     MCTF_CHECK_CM_ERR(res, res);
2640     tsHeight = (DIVUP(p_ctrl->CropH, blsize) * multiplier);
2641     tsWidthFull = (DIVUP(p_ctrl->CropW, blsize) * multiplier);
2642     tsWidth = tsWidthFull;
2643 
2644     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2645         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
2646 
2647     threadSpace = 0;
2648     res = MCTF_RUN_TASK(kernelMc1r, task != 0);
2649     MCTF_CHECK_CM_ERR(res, res);
2650 
2651     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2652     {
2653         mfxU16
2654             start_mbX = tsWidth;
2655         tsWidth = tsWidthFull - tsWidth;
2656         res = MCTF_SET_KERNELMc(start_mbX, DIVUP(p_ctrl->CropY, blsize) * multiplier, 1, 0);
2657         MCTF_CHECK_CM_ERR(res, res);
2658         // the rest of frame TS
2659         res = MCTF_RUN_TASK(kernelMc1r, task != 0);
2660         MCTF_CHECK_CM_ERR(res, res);
2661     }
2662     res = e->WaitForTaskFinished();
2663     MCTF_CHECK_CM_ERR(res, res);
2664     UINT64 executionTime;
2665     e->GetExecutionTime(executionTime);
2666     exeTime += executionTime / 1000;
2667     device->DestroyThreadSpace(threadSpace);
2668     queue->DestroyEvent(e);
2669     e = 0;
2670     return res;
2671 }
2672 
MCTF_RUN_BLEND(mfxU8 srcNum,mfxU8 refNum)2673 mfxI32 CMC::MCTF_RUN_BLEND(
2674     mfxU8 srcNum,
2675     mfxU8 refNum
2676 )
2677 {
2678     mfxU16 multiplier = 2;
2679     res = MCTF_SET_KERNELMc(DIVUP(p_ctrl->CropX, blsize) * multiplier , DIVUP(p_ctrl->CropY, blsize) * multiplier, srcNum, refNum);
2680     MCTF_CHECK_CM_ERR(res, res);
2681     tsHeight = (DIVUP(p_ctrl->CropH, blsize) * multiplier);
2682     tsWidthFull = (DIVUP(p_ctrl->CropW, blsize) * multiplier);
2683     tsWidth = tsWidthFull;
2684 
2685     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2686         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
2687 
2688     threadSpace = 0;
2689     res = MCTF_RUN_TASK(kernelMc1r, task != 0);
2690     MCTF_CHECK_CM_ERR(res, res);
2691 
2692     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2693     {
2694         mfxU16
2695             start_mbX = tsWidth;
2696         tsWidth = tsWidthFull - tsWidth;
2697         res = MCTF_SET_KERNELMc(start_mbX, DIVUP(p_ctrl->CropY, blsize) * multiplier, srcNum, refNum);
2698         MCTF_CHECK_CM_ERR(res, res);
2699         // the rest of frame TS
2700         res = MCTF_RUN_TASK(kernelMc1r, task != 0);
2701         MCTF_CHECK_CM_ERR(res, res);
2702     }
2703     res = e->WaitForTaskFinished();
2704     MCTF_CHECK_CM_ERR(res, res);
2705     device->DestroyThreadSpace(threadSpace);
2706     queue->DestroyEvent(e);
2707     e = 0;
2708     return res;
2709 }
2710 
MCTF_RUN_BLEND2R()2711 mfxI32 CMC::MCTF_RUN_BLEND2R()
2712 {
2713     mfxU16 multiplier = 2;
2714     res = MCTF_SET_KERNELMc2r(DIVUP(p_ctrl->CropX, blsize) * multiplier, DIVUP(p_ctrl->CropY, blsize) * multiplier);
2715     MCTF_CHECK_CM_ERR(res, res);
2716 
2717     tsHeightMC = (DIVUP(p_ctrl->CropH, blsize) * multiplier);
2718     tsWidthFullMC = (DIVUP(p_ctrl->CropW, blsize) * multiplier);
2719     tsWidthMC = tsWidthFullMC;
2720 
2721     if (tsWidthFullMC > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2722         tsWidthMC = (tsWidthFullMC >> 1) & ~1;  // must be even for 32x32 blocks
2723 
2724     threadSpaceMC = 0;
2725     res = MCTF_RUN_MCTASK(kernelMc2r, task != 0);
2726     MCTF_CHECK_CM_ERR(res, res);
2727 
2728     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2729     {
2730         mfxU16 start_mbX = tsWidthMC;
2731         tsWidthMC = tsWidthFullMC - tsWidthMC;
2732         res = MCTF_SET_KERNELMc2r(start_mbX, DIVUP(p_ctrl->CropY, blsize) * multiplier);
2733         MCTF_CHECK_CM_ERR(res, res);
2734         // the rest of frame TS
2735         res = MCTF_RUN_MCTASK(kernelMc2r, task != 0);
2736         MCTF_CHECK_CM_ERR(res, res);
2737     }
2738     res = e->WaitForTaskFinished();
2739     MCTF_CHECK_CM_ERR(res, res);
2740     UINT64 executionTime;
2741     e->GetExecutionTime(executionTime);
2742     exeTime += executionTime / 1000;
2743     device->DestroyThreadSpace(threadSpaceMC);
2744     queue->DestroyEvent(e);
2745     e = 0;
2746     return res;
2747 }
2748 
MCTF_RUN_BLEND2R_DEN()2749 mfxI32 CMC::MCTF_RUN_BLEND2R_DEN()
2750 {
2751     mfxU16 multiplier = 2;
2752     res = MCTF_SET_KERNELMc2rDen(DIVUP(p_ctrl->CropX, blsize) * multiplier, DIVUP(p_ctrl->CropY, blsize) * multiplier);
2753     MCTF_CHECK_CM_ERR(res, res);
2754     tsHeight = (DIVUP(p_ctrl->CropH, blsize) * multiplier);
2755     tsWidthFull = (DIVUP(p_ctrl->CropW, blsize) * multiplier);
2756     tsWidth = tsWidthFull;
2757 
2758     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2759         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
2760 
2761     threadSpace = 0;
2762     res = MCTF_RUN_TASK(kernelMc2r, task != 0);
2763     MCTF_CHECK_CM_ERR(res, res);
2764 
2765     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2766     {
2767         mfxU16
2768             start_mbX = tsWidth;
2769         tsWidth = tsWidthFull - tsWidth;
2770 
2771         res = MCTF_SET_KERNELMc2rDen(start_mbX, DIVUP(p_ctrl->CropY, blsize) * multiplier);
2772         MCTF_CHECK_CM_ERR(res, res);
2773         // the rest of frame TS
2774         res = MCTF_RUN_TASK(kernelMc2r, task != 0);
2775         MCTF_CHECK_CM_ERR(res, res);
2776     }
2777     res = e->WaitForTaskFinished();
2778     MCTF_CHECK_CM_ERR(res, res);
2779     device->DestroyThreadSpace(threadSpace);
2780     queue->DestroyEvent(e);
2781     e = 0;
2782     return res;
2783 }
2784 
MCTF_RUN_BLEND4R(DRT typeRun)2785 mfxI32 CMC::MCTF_RUN_BLEND4R(
2786     DRT typeRun
2787 )
2788 {
2789     if (typeRun > 1)
2790         return MFX_ERR_INVALID_VIDEO_PARAM;
2791     mfxU16 multiplier = 2;
2792     res = MCTF_SET_KERNELMc4r(DIVUP(p_ctrl->CropX, blsize) * multiplier, DIVUP(p_ctrl->CropY, blsize) * multiplier, (mfxU8)typeRun);
2793     MCTF_CHECK_CM_ERR(res, res);
2794     tsHeight = (DIVUP(p_ctrl->CropH, blsize) * multiplier);
2795     tsWidthFull = (DIVUP(p_ctrl->CropW, blsize) * multiplier);
2796     tsWidth = tsWidthFull;
2797 
2798     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2799         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
2800 
2801     threadSpace = 0;
2802     res = MCTF_RUN_TASK(kernelMc2r, task != 0);
2803     MCTF_CHECK_CM_ERR(res, res);
2804 
2805     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2806     {
2807         mfxU16
2808             start_mbX = tsWidth;
2809         tsWidth = tsWidthFull - tsWidth;
2810         res = MCTF_SET_KERNELMc4r(start_mbX, DIVUP(p_ctrl->CropY, blsize) * multiplier, (mfxU8)typeRun);
2811         MCTF_CHECK_CM_ERR(res, res);
2812         // the rest of frame TS
2813         res = MCTF_RUN_TASK(kernelMc2r, task != 0);
2814         MCTF_CHECK_CM_ERR(res, res);
2815     }
2816     res = e->WaitForTaskFinished();
2817     MCTF_CHECK_CM_ERR(res, res);
2818     device->DestroyThreadSpace(threadSpace);
2819     queue->DestroyEvent(e);
2820     e = 0;
2821     return res;
2822 }
2823 
MCTF_RUN_MERGE()2824 mfxI32 CMC::MCTF_RUN_MERGE()
2825 {
2826     res = MCTF_SET_KERNELMcMerge(DIVUP(p_ctrl->CropX, 16), DIVUP(p_ctrl->CropY, 16));
2827     MCTF_CHECK_CM_ERR(res, res);
2828     tsHeight = DIVUP(p_ctrl->CropH, 16);
2829     tsWidthFull = DIVUP(p_ctrl->CropW, 16);
2830     tsWidth = tsWidthFull;
2831 
2832     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2833         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
2834 
2835     threadSpace = 0;
2836     res = MCTF_RUN_TASK(kernelMc4r, task != 0);
2837     MCTF_CHECK_CM_ERR(res, res);
2838 
2839     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2840     {
2841         mfxU16
2842             start_mbX = tsWidth;
2843         tsWidth = tsWidthFull - tsWidth;
2844         res = MCTF_SET_KERNELMc4r(start_mbX, DIVUP(p_ctrl->CropY, 16));
2845         MCTF_CHECK_CM_ERR(res, res);
2846         // the rest of frame TS
2847         res = MCTF_RUN_TASK(kernelMc4r, task != 0);
2848         MCTF_CHECK_CM_ERR(res, res);
2849     }
2850     res = e->WaitForTaskFinished();
2851     MCTF_CHECK_CM_ERR(res, res);
2852     device->DestroyThreadSpace(threadSpace);
2853     queue->DestroyEvent(e);
2854     e = 0;
2855     return res;
2856 }
2857 
MCTF_RUN_BLEND4R(SurfaceIndex * multiIndex)2858 mfxI32 CMC::MCTF_RUN_BLEND4R(
2859     SurfaceIndex * multiIndex
2860 )
2861 {
2862     mfxU16 multiplier = 2;
2863     res = MCTF_SET_KERNELMc4r(DIVUP(p_ctrl->CropX, blsize) * multiplier, DIVUP(p_ctrl->CropY, blsize) * multiplier, multiIndex);
2864     MCTF_CHECK_CM_ERR(res, res);
2865     tsHeight = (DIVUP(p_ctrl->CropH, blsize) * multiplier);
2866     tsWidthFull = (DIVUP(p_ctrl->CropW, blsize) * multiplier);
2867     tsWidth = tsWidthFull;
2868 
2869     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2870         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
2871 
2872     threadSpace = 0;
2873     res = MCTF_RUN_TASK(kernelMc2r, task != 0);
2874     MCTF_CHECK_CM_ERR(res, res);
2875 
2876     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
2877     {
2878         mfxU16
2879             start_mbX = tsWidth;
2880         tsWidth = tsWidthFull - tsWidth;
2881         res = MCTF_SET_KERNELMc4r(start_mbX, DIVUP(p_ctrl->CropY, blsize) * multiplier, multiIndex);
2882         MCTF_CHECK_CM_ERR(res, res);
2883         res = MCTF_RUN_TASK(kernelMc2r, task != 0);
2884         MCTF_CHECK_CM_ERR(res, res);
2885     }
2886     res = e->WaitForTaskFinished();
2887     MCTF_CHECK_CM_ERR(res, res);
2888     device->DestroyThreadSpace(threadSpace);
2889     queue->DestroyEvent(e);
2890     e = 0;
2891     return res;
2892 }
2893 
RotateBufferA()2894 void CMC::RotateBufferA()
2895 {
2896     std::swap(QfIn[0], QfIn[1]);
2897     std::swap(QfIn[0], QfIn[2]);
2898 }
2899 
RotateBufferB()2900 void CMC::RotateBufferB()
2901 {
2902     std::swap(QfIn[0], QfIn[1]);
2903     std::swap(QfIn[1], QfIn[2]);
2904     std::swap(QfIn[2], QfIn[3]);
2905 }
2906 
RotateBuffer()2907 void CMC::RotateBuffer()
2908 {
2909     mfxU8 correction = ((QfIn.size() > 3) && (firstFrame < 3)) << 1;
2910     for (mfxU8 i = 0; i < QfIn.size() - 1 - correction; i++)
2911         std::swap(QfIn[i], QfIn[i + 1]);
2912 }
2913 
AssignSceneNumber()2914 void CMC::AssignSceneNumber()
2915 {
2916     for (mfxU8 i = 0; i < QfIn.size(); i++)
2917         scene_numbers[i] = QfIn[i].scene_idx;
2918 }
2919 
MCTF_RUN_ME_1REF()2920 mfxI32 CMC::MCTF_RUN_ME_1REF()
2921 {
2922     res = MCTF_RUN_ME(genxRefs1, idxMv_1);
2923     MCTF_CHECK_CM_ERR(res, res);
2924 
2925     res = e->WaitForTaskFinished();
2926     MCTF_CHECK_CM_ERR(res, res);
2927     UINT64 executionTime;
2928     e->GetExecutionTime(executionTime);
2929     exeTime += executionTime / 1000;
2930     device->DestroyThreadSpace(threadSpace);
2931     queue->DestroyEvent(e);
2932     device->DestroyVmeSurfaceG7_5(genxRefs1);
2933     e = 0;
2934 
2935     if (pMCTF_NOA_func)
2936         (this->*(pMCTF_NOA_func))(m_adaptControl);
2937 
2938     return res;
2939 }
2940 
MCTF_RUN_ME_2REF_HE()2941 mfxI32 CMC::MCTF_RUN_ME_2REF_HE()
2942 {
2943     res = MCTF_RUN_ME_MC_HE(genxRefs1, genxRefs2, idxMv_1, idxMv_2, forward_distance, backward_distance, 0);
2944     MCTF_CHECK_CM_ERR(res, res);
2945     return res;
2946 }
2947 
MCTF_RUN_ME_2REF()2948 mfxI32 CMC::MCTF_RUN_ME_2REF()
2949 {
2950     res = MCTF_RUN_ME_MC_H(genxRefs1, genxRefs2, idxMv_1, idxMv_2, forward_distance, backward_distance, 0);
2951     MCTF_CHECK_CM_ERR(res, res);
2952     return res;
2953 }
2954 
MCTF_RUN_ME_4REF()2955 mfxI32 CMC::MCTF_RUN_ME_4REF()
2956 {
2957     res = MCTF_RUN_ME_MC_H(genxRefs1, genxRefs2, idxMv_1, idxMv_2, forward_distance, backward_distance, 1);
2958     MCTF_CHECK_CM_ERR(res, res);
2959     res = MCTF_RUN_ME_MC_H(genxRefs3, genxRefs4, idxMv_3, idxMv_4, forward_distance, backward_distance, 2);
2960     return res;
2961 }
2962 
2963 
MCTF_BLEND4R()2964 mfxI32 CMC::MCTF_BLEND4R()
2965 {
2966     res = MCTF_RUN_BLEND4R(DEN_CLOSE_RUN);
2967     MCTF_CHECK_CM_ERR(res, res);
2968     res = MCTF_RUN_BLEND4R(DEN_FAR_RUN);
2969     MCTF_CHECK_CM_ERR(res, res);
2970     res = MCTF_RUN_MERGE();
2971     MCTF_CHECK_CM_ERR(res, res);
2972     return res;
2973 }
2974 
MCTF_RUN_MCTF_DEN_1REF(bool)2975 mfxI32 CMC::MCTF_RUN_MCTF_DEN_1REF(
2976     bool
2977 )
2978 {
2979     if (pMCTF_LOAD_func)
2980     {
2981         res = (this->*(pMCTF_LOAD_func))();
2982         MCTF_CHECK_CM_ERR(res, res);
2983     }
2984     AssignSceneNumber();
2985     if (pMCTF_ME_func)
2986     {
2987         res = (this->*(pMCTF_ME_func))();
2988         MCTF_CHECK_CM_ERR(res, res);
2989     }
2990     if (pMCTF_MERGE_func)
2991     {
2992         res = (this->*(pMCTF_MERGE_func))();
2993         MCTF_CHECK_CM_ERR(res, res);
2994     }
2995     if (pMCTF_SpDen_func)
2996         res = (this->*(pMCTF_SpDen_func))();
2997     RotateBuffer();
2998     return res;
2999 }
3000 
MCTF_RUN_MCTF_DEN(bool notInPipeline)3001 mfxI32 CMC::MCTF_RUN_MCTF_DEN(
3002     bool notInPipeline
3003 )
3004 {
3005     if ((QfIn[1].filterStrength > 0) || notInPipeline)
3006     {
3007         if (pMCTF_LOAD_func)
3008         {
3009             res = (this->*(pMCTF_LOAD_func))();
3010             MCTF_CHECK_CM_ERR(res, res);
3011         }
3012         AssignSceneNumber();
3013         if (pMCTF_ME_func)
3014         {
3015             res = (this->*(pMCTF_ME_func))();
3016             MCTF_CHECK_CM_ERR(res, res);
3017         }
3018         if (pMCTF_MERGE_func)
3019         {
3020             res = (this->*(pMCTF_MERGE_func))();
3021             MCTF_CHECK_CM_ERR(res, res);
3022         }
3023         if (pMCTF_SpDen_func)
3024             res = (this->*(pMCTF_SpDen_func))();
3025     }
3026     RotateBuffer();
3027     return res;
3028 }
3029 
MCTF_RUN_MCTF_DEN_4REF(bool)3030 mfxI32 CMC::MCTF_RUN_MCTF_DEN_4REF(
3031     bool
3032 )
3033 {
3034     res = (this->*(pMCTF_LOAD_func))();
3035     MCTF_CHECK_CM_ERR(res, res);
3036     AssignSceneNumber();
3037     res = (this->*(pMCTF_ME_func))();
3038     MCTF_CHECK_CM_ERR(res, res);
3039     res = (this->*(pMCTF_MERGE_func))();
3040     MCTF_CHECK_CM_ERR(res, res);
3041     if (pMCTF_SpDen_func)
3042         res = (this->*(pMCTF_SpDen_func))();
3043     RotateBuffer();
3044     return res;
3045 }
3046 
MCTF_RUN_AMCTF_DEN()3047 mfxI32 CMC::MCTF_RUN_AMCTF_DEN()
3048 {
3049     res = (this->*(pMCTF_LOAD_func))();
3050     MCTF_CHECK_CM_ERR(res, res);
3051     AssignSceneNumber();
3052     res = MCTF_RUN_ME(genxRefs1, genxRefs2, idxMv_1, idxMv_2, forward_distance, backward_distance);
3053     MCTF_CHECK_CM_ERR(res, res);
3054     res = MCTF_RUN_BLEND2R();
3055     MCTF_CHECK_CM_ERR(res, res);
3056     res = MCTF_RUN_Denoise();
3057     MCTF_CHECK_CM_ERR(res, res);
3058     RotateBuffer();
3059     return res;
3060 }
3061 
MCTF_RUN_AMCTF()3062 mfxI32 CMC::MCTF_RUN_AMCTF()
3063 {
3064     res = MCTF_RUN_Denoise(1);
3065     MCTF_CHECK_CM_ERR(res, res);
3066     return res;
3067 }
3068 
MCTF_RUN_AMCTF(mfxU16 srcNum)3069 mfxI32 CMC::MCTF_RUN_AMCTF(mfxU16 srcNum)
3070 {
3071     res = MCTF_RUN_Denoise(srcNum);
3072     MCTF_CHECK_CM_ERR(res, res);
3073     MctfState = AMCTF_READY;
3074     return res;
3075 }
3076 
MCTF_RUN_Denoise(mfxU16 srcNum)3077 mfxI32 CMC::MCTF_RUN_Denoise(mfxU16 srcNum)
3078 {
3079     if (QfIn[srcNum].filterStrength == 21)
3080         p_ctrl->sTh = MCTFSTRENGTH * 50 / 25;
3081     else
3082         p_ctrl->sTh = QfIn[srcNum].filterStrength * 50 / 25;
3083     res = ctrlBuf->WriteSurface((const mfxU8 *)p_ctrl.get(), NULL, sizeof(MeControlSmall));
3084     MCTF_CHECK_CM_ERR(res, res);
3085     res = MCTF_SET_KERNELDe(srcNum, 0, 0);
3086     MCTF_CHECK_CM_ERR(res, res);
3087     p_ctrl->sTh = 0;
3088     tsHeight    = DIVUP(p_ctrl->height, 8);
3089     tsWidthFull = DIVUP(p_ctrl->width,  8);
3090     tsWidth     = tsWidthFull;
3091 
3092     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW) {
3093         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
3094     }
3095 
3096     threadSpace = 0;
3097     res = MCTF_RUN_TASK(kernelMcDen, task != 0);
3098     MCTF_CHECK_CM_ERR(res, res);
3099 
3100     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
3101     {
3102         mfxU16
3103             start_mbX = tsWidth;
3104         tsWidth = tsWidthFull - tsWidth;
3105         res = MCTF_SET_KERNELDe(srcNum, start_mbX, 0);
3106         MCTF_CHECK_CM_ERR(res, res);
3107         if (threadSpace != NULL) {
3108             res = device->DestroyThreadSpace(threadSpace);
3109             MCTF_CHECK_CM_ERR(res, res);
3110         }
3111         // the rest of frame TS
3112         res = MCTF_RUN_TASK(kernelMcDen, task != 0);
3113         MCTF_CHECK_CM_ERR(res, res);
3114     }
3115     res = e->WaitForTaskFinished();
3116     MCTF_CHECK_CM_ERR(res, res);
3117 
3118     UINT64 executionTime;
3119     e->GetExecutionTime(executionTime);
3120     exeTime += executionTime / 1000;
3121     return res;
3122 }
3123 
MCTF_RUN_Denoise()3124 mfxI32 CMC::MCTF_RUN_Denoise()
3125 {
3126     res = MCTF_SET_KERNELDe(DIVUP(p_ctrl->CropX, 8), DIVUP(p_ctrl->CropY, 8));
3127     MCTF_CHECK_CM_ERR(res, res);
3128     tsHeight = DIVUP(p_ctrl->CropH, 8);
3129     tsWidthFull = DIVUP(p_ctrl->CropW, 8);
3130     tsWidth = tsWidthFull;
3131 
3132     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
3133         tsWidth = (tsWidthFull >> 1) & ~1;  // must be even for 32x32 blocks
3134 
3135     threadSpace = 0;
3136     res = MCTF_RUN_TASK(kernelMcDen, task != 0);
3137     MCTF_CHECK_CM_ERR(res, res);
3138 
3139     if (tsWidthFull > CM_MAX_THREADSPACE_WIDTH_FOR_MW)
3140     {
3141         mfxU16
3142             start_mbX = tsWidth;
3143         tsWidth = tsWidthFull - tsWidth;
3144         res = MCTF_SET_KERNELDe(start_mbX, DIVUP(p_ctrl->CropY, 8));
3145         MCTF_CHECK_CM_ERR(res, res);
3146         res = MCTF_RUN_TASK(kernelMcDen, task != 0);
3147         MCTF_CHECK_CM_ERR(res, res);
3148     }
3149     res = e->WaitForTaskFinished();
3150     MCTF_CHECK_CM_ERR(res, res);
3151     UINT64 executionTime;
3152     e->GetExecutionTime(executionTime);
3153     exeTime += executionTime / 1000;
3154     return res;
3155 }
3156 
IM_SURF_PUT(CmSurface2D * p_surface,mfxU8 * p_data)3157 mfxU32 CMC::IM_SURF_PUT(
3158     CmSurface2D *p_surface,
3159     mfxU8 *p_data)
3160 {
3161     CM_STATUS
3162         status = CM_STATUS_FLUSHED;
3163     res = queue->EnqueueCopyCPUToGPU(p_surface, p_data, copyEv);
3164     MCTF_CHECK_CM_ERR(res, res);
3165     copyEv->GetStatus(status);
3166     while (status != CM_STATUS_FINISHED)
3167         copyEv->GetStatus(status);
3168     return res;
3169 }
3170 
IntBufferUpdate(bool isSceneChange,bool isIntraFrame,bool doIntraFiltering)3171 void CMC::IntBufferUpdate(
3172     bool isSceneChange,
3173     bool isIntraFrame,
3174     bool doIntraFiltering)
3175 {
3176     size_t
3177         buffer_size = QfIn.size() - 1;
3178     if (bufferCount > buffer_size) {
3179         printf("Error: Invalid frame buffer position\n");
3180         exit(-1);
3181     }
3182     if (bufferCount == 0)
3183         QfIn.back().frame_number = 0;
3184     else
3185         QfIn.back().frame_number = (QfIn.end() - 2)->frame_number + 1;
3186 
3187     if (!firstFrame)
3188         sceneNum += isSceneChange;
3189 
3190     QfIn.back().isSceneChange = (firstFrame || isSceneChange);
3191     QfIn.back().isIntra = isIntraFrame;
3192 
3193     if (isSceneChange || isIntraFrame || bufferCount == 0)
3194         countFrames = 0;
3195     else
3196         countFrames++;
3197     QfIn.back().frame_relative_position = countFrames;
3198     QfIn.back().frame_added             = false;
3199     QfIn.back().scene_idx               = sceneNum;
3200     if((QfIn.back().isSceneChange || QfIn.back().isIntra) && doIntraFiltering)
3201         m_doFilterFrame = true;
3202 }
3203 
BufferFilterAssignment(mfxU16 * filterStrength,bool doIntraFiltering,bool isAnchorFrame,bool isSceneChange)3204 void CMC::BufferFilterAssignment(
3205     mfxU16 * filterStrength,
3206     bool     doIntraFiltering,
3207     bool     isAnchorFrame,
3208     bool     isSceneChange)
3209 {
3210     if (!filterStrength)
3211     {
3212         if (isAnchorFrame && isSceneChange)
3213         {
3214             QfIn.back().filterStrength = doIntraFiltering ? MCTFSTRENGTH : MCTFNOFILTER;
3215 #ifdef MFX_MCTF_DEBUG_PRINT
3216             ASC_PRINTF("\nI frame denoising is: %i, strength set at: %i\n", doIntraFiltering, QfIn[bufferCount].filterStrength));
3217 #endif
3218             gopBasedFilterStrength = MCTFADAPTIVE;
3219         }
3220         else if (isAnchorFrame)
3221             QfIn.back().filterStrength = gopBasedFilterStrength;
3222         else
3223             QfIn.back().filterStrength = MCTFNOFILTER;
3224     }
3225     else
3226         QfIn.back().filterStrength = *filterStrength;
3227 }
3228 
MCTF_PUT_FRAME(void * frameInData,mfxHDLPair frameOutHandle,CmSurface2D ** frameOutData,bool isCmSurface,mfxU16 * filterStrength,bool needsOutput,bool doIntraFiltering)3229 mfxStatus CMC::MCTF_PUT_FRAME(
3230     void         * frameInData,
3231     mfxHDLPair     frameOutHandle,
3232     CmSurface2D ** frameOutData,
3233     bool           isCmSurface,
3234     mfxU16       * filterStrength,
3235     bool           needsOutput,
3236     bool           doIntraFiltering
3237 )
3238 {
3239     if (!frameInData)
3240         return MFX_ERR_UNDEFINED_BEHAVIOR;
3241     if (isCmSurface)
3242     {
3243         mfxFrameSurface1 *
3244             mfxFrame = (mfxFrameSurface1 *)frameInData;
3245         mfxHDLPair
3246             handle;
3247         // if a surface is opaque, need to extract normal surface
3248         mfxFrameSurface1
3249             * pSurf = m_pCore->GetNativeSurface(mfxFrame);
3250         QfIn.back().mfxFrame = pSurf ? pSurf : mfxFrame;
3251         if (pSurf)
3252         {
3253             MFX_SAFE_CALL(m_pCore->GetFrameHDL(QfIn.back().mfxFrame->Data.MemId, reinterpret_cast<mfxHDL*>(&handle)));
3254         }
3255         else
3256         {
3257             MFX_SAFE_CALL(m_pCore->GetExternalFrameHDL(QfIn.back().mfxFrame->Data.MemId, reinterpret_cast<mfxHDL*>(&handle)));
3258         }
3259         MFX_SAFE_CALL(IM_SURF_SET(reinterpret_cast<AbstractSurfaceHandle>(handle.first), &QfIn.back().frameData, &QfIn.back().fIdx));
3260     }
3261     else
3262     {
3263         res = IM_SURF_PUT(QfIn.back().frameData, (mfxU8*)frameInData);
3264         MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
3265     }
3266     QfIn.back().frame_added = true;
3267     if (needsOutput)
3268     {
3269         SurfaceIndex
3270             *fIdx = nullptr;
3271         MFX_SAFE_CALL(IM_SURF_SET(reinterpret_cast<AbstractSurfaceHandle>(frameOutHandle.first), frameOutData, &fIdx));
3272         QfIn.back().fOut    = *frameOutData;
3273         QfIn.back().fIdxOut = fIdx;
3274     }
3275 
3276     if (m_doFilterFrame)
3277         BufferFilterAssignment(filterStrength, doIntraFiltering, needsOutput, QfIn.back().isSceneChange);
3278     else
3279         QfIn.back().filterStrength = MCTFNOFILTER;
3280     return MFX_ERR_NONE;
3281 }
3282 
MCTF_PUT_FRAME(IntMctfParams * pMctfControl,CmSurface2D * InSurf,CmSurface2D * OutSurf)3283 mfxStatus CMC::MCTF_PUT_FRAME(
3284     IntMctfParams * pMctfControl,
3285     CmSurface2D   * InSurf,
3286     CmSurface2D   * OutSurf
3287 )
3288 {
3289     lastFrame = 0;
3290     if (!InSurf)
3291         return MFX_ERR_UNDEFINED_BEHAVIOR;
3292     INT cmSts = 0;
3293 
3294     SurfaceIndex* idxFrom;
3295     cmSts = InSurf->GetIndex(idxFrom);
3296     MFX_CHECK((CM_SUCCESS == cmSts), MFX_ERR_DEVICE_FAILED);
3297 
3298     MFX_SAFE_CALL(pSCD->PutFrameProgressive(idxFrom));
3299 
3300     MCTF_PUT_FRAME(
3301         pMctfControl,
3302         OutSurf,
3303         pSCD->Get_frame_shot_Decision()
3304     );
3305     return MFX_ERR_NONE;
3306 }
3307 
MCTF_PUT_FRAME(IntMctfParams * pMctfControl,CmSurface2D * OutSurf,mfxU32 schgDesicion)3308 mfxStatus CMC::MCTF_PUT_FRAME(
3309     IntMctfParams * pMctfControl,
3310     CmSurface2D   * OutSurf,
3311     mfxU32          schgDesicion
3312 )
3313 {
3314     lastFrame = 0;
3315     sceneNum += schgDesicion;
3316     MFX_SAFE_CALL(MCTF_UpdateRTParams(pMctfControl));
3317     MFX_SAFE_CALL(MCTF_PUT_FRAME(sceneNum, OutSurf));
3318     forward_distance = -1;
3319     backward_distance = 1;
3320     countFrames++;
3321     return MFX_ERR_NONE;
3322 }
3323 
MCTF_DO_FILTERING_IN_AVC()3324 mfxStatus CMC::MCTF_DO_FILTERING_IN_AVC()
3325 {
3326     // do filtering based on temporal mode & how many frames are
3327     // already in the queue:
3328     res = MFX_ERR_NONE;
3329     switch (number_of_References)
3330     {
3331     case 2://else if (number_of_References == 2)
3332     {
3333         if (bufferCount < 2) /*One frame delay*/
3334         {
3335             firstFrame = 0;
3336             RotateBuffer();
3337             MctfState = AMCTF_NOT_READY;
3338             return MFX_ERR_NONE;
3339         }
3340 
3341         MCTF_UpdateANDApplyRTParams(1);
3342         if (QfIn[1].fOut)
3343         {
3344             mco    = QfIn[1].fOut;
3345             idxMco = QfIn[1].fIdxOut;
3346             if (QfIn[1].isSceneChange)
3347             {
3348                 if(QfIn[1].filterStrength)
3349                     res = MCTF_RUN_AMCTF(1);
3350                 RotateBuffer();
3351             }
3352             else
3353                 res = (this->*(pMCTF_func))(false);
3354             CurrentIdx2Out = DefaultIdx2Out;
3355             MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
3356             QfIn.front().fOut    = mco    = nullptr;
3357             QfIn.front().fIdxOut = idxMco = nullptr;
3358         }
3359         else
3360             RotateBuffer();
3361         break;
3362     };
3363     break;
3364     default://    else
3365         return MFX_ERR_UNDEFINED_BEHAVIOR;
3366     }
3367     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
3368     return MFX_ERR_NONE;
3369 }
3370 
MCTF_QUERY_FILTER_STRENGTH()3371 mfxU16 CMC::MCTF_QUERY_FILTER_STRENGTH()
3372 {
3373     return QfIn[1].filterStrength;
3374 }
3375 
MCTF_DO_FILTERING()3376 mfxStatus CMC::MCTF_DO_FILTERING()
3377 {
3378     // do filtering based on temporal mode & how many frames are
3379     // already in the queue:
3380     switch (number_of_References)
3381     {
3382     case 4://if (number_of_References == 4)
3383     {
3384         if (bufferCount < 3)
3385         {
3386             MctfState = AMCTF_NOT_READY;
3387             mco = nullptr;
3388             return MFX_ERR_NONE;
3389         }
3390 
3391         switch (firstFrame)
3392         {
3393         case 1:
3394         {
3395             pMCTF_MERGE_func = NULL;
3396             //todo: check is it correct that the current frame is 0?
3397             MCTF_UpdateANDApplyRTParams(0);
3398             pMCTF_ME_func = &CMC::MCTF_RUN_ME_2REF;
3399             pMCTF_LOAD_func = &CMC::MCTF_LOAD_2REF;
3400             RotateBufferA();
3401             res = MCTF_RUN_MCTF_DEN(true);
3402             CurrentIdx2Out = 0;
3403             MctfState = AMCTF_READY;
3404             firstFrame = 2;
3405             break;
3406         }
3407         case 2:
3408         {
3409             //todo: check is it correct that the current frame is 1?
3410             MCTF_UpdateANDApplyRTParams(1);
3411             res = MCTF_RUN_MCTF_DEN(true);
3412             RotateBufferA();
3413             CurrentIdx2Out = 1;
3414             MctfState = AMCTF_READY;
3415             firstFrame = 3;
3416 
3417             pMCTF_MERGE_func = &CMC::MCTF_RUN_MERGE;
3418             pMCTF_ME_func = &CMC::MCTF_RUN_ME_4REF;
3419             pMCTF_LOAD_func = &CMC::MCTF_LOAD_4REF;
3420             break;
3421         }
3422 
3423         default:
3424         {
3425             MCTF_UpdateANDApplyRTParams(2);
3426             res = (this->*(pMCTF_func))(true);
3427             CurrentIdx2Out = DefaultIdx2Out;
3428             MctfState = AMCTF_READY;
3429             break;
3430         }
3431         }
3432     };
3433     break;
3434     case 2://else if (number_of_References == 2)
3435     {
3436         if (bufferCount < 2) /*One frame delay*/
3437         {
3438             MctfState = AMCTF_NOT_READY;
3439             mco = nullptr;
3440             return MFX_ERR_NONE;
3441         }
3442 
3443         switch (firstFrame)
3444         {
3445             case 0:
3446             {
3447                 MCTF_UpdateANDApplyRTParams(1);
3448                 res = (this->*(pMCTF_func))(true);
3449                 CurrentIdx2Out = DefaultIdx2Out;
3450                 MctfState = AMCTF_READY;
3451                 break;
3452             }
3453             default:
3454             {
3455                 MCTF_UpdateANDApplyRTParams(0);
3456                 res = MCTF_RUN_AMCTF(0);
3457                 firstFrame = 0;
3458                 CurrentIdx2Out = 0;
3459                 MctfState = AMCTF_READY;
3460                 break;
3461             }
3462         }
3463     };
3464     break;
3465     case 1: //else if (number_of_References == 1)
3466     {
3467         if (firstFrame)
3468         {
3469             MCTF_UpdateANDApplyRTParams(0);
3470             res = MCTF_RUN_AMCTF(0);
3471             firstFrame = 0;
3472             MctfState = AMCTF_READY;
3473         }
3474         else
3475         {
3476             MCTF_UpdateANDApplyRTParams(1);
3477             if (QfIn[0].scene_idx != QfIn[1].scene_idx)
3478             {
3479                 res = MCTF_RUN_AMCTF();
3480                 RotateBuffer();
3481             }
3482             else
3483                 res = (this->*(pMCTF_func))(true);
3484             MctfState = AMCTF_READY;
3485         }
3486         CurrentIdx2Out = DefaultIdx2Out;
3487     };
3488     break;
3489     case 0://else if (number_of_References == 0)
3490     {
3491         MCTF_UpdateANDApplyRTParams(0);
3492         res = MCTF_RUN_AMCTF(0);
3493         firstFrame = 0;
3494         MctfState = AMCTF_READY;
3495         CurrentIdx2Out = DefaultIdx2Out;
3496     };
3497     break;
3498     default://    else
3499         return MFX_ERR_UNDEFINED_BEHAVIOR;
3500     }
3501     MCTF_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
3502     return MFX_ERR_NONE;
3503 }
3504 
MCTF_CLOSE()3505 void CMC::MCTF_CLOSE()
3506 {
3507     if (kernelMe)
3508         device->DestroyKernel(kernelMe);
3509     if (kernelMeB)
3510         device->DestroyKernel(kernelMeB);
3511     if (kernelMeB2)
3512         device->DestroyKernel(kernelMeB2);
3513     if (kernelMcDen)
3514         device->DestroyKernel(kernelMcDen);
3515     if (kernelMc1r)
3516         device->DestroyKernel(kernelMc1r);
3517     if (kernelMc2r)
3518         device->DestroyKernel(kernelMc2r);
3519     if (kernelMc4r)
3520         device->DestroyKernel(kernelMc4r);
3521     if (programMe)
3522         device->DestroyProgram(programMe);
3523     if (programMc)
3524         device->DestroyProgram(programMc);
3525     if (programDe)
3526         device->DestroyProgram(programDe);
3527     if (ctrlBuf)
3528         device->DestroySurface(ctrlBuf);
3529 
3530 
3531     if (task)
3532         device->DestroyTask(task);
3533     if (e)
3534         queue->DestroyEvent(e);
3535     if (copyEv)
3536         queue->DestroyEvent(copyEv);
3537 
3538     if (mco2)
3539         device->DestroySurface(mco2);
3540     if (idxMv_1)
3541     {
3542         device->DestroySurface2DUP(mv_1);
3543         CM_ALIGNED_FREE(mvSys1);
3544     }
3545     if (idxMv_2)
3546     {
3547         device->DestroySurface2DUP(mv_2);
3548         CM_ALIGNED_FREE(mvSys2);
3549     }
3550     if (idxMv_3)
3551     {
3552         device->DestroySurface2DUP(mv_3);
3553         CM_ALIGNED_FREE(mvSys3);
3554     }
3555     if (idxMv_4)
3556     {
3557         device->DestroySurface2DUP(mv_4);
3558         CM_ALIGNED_FREE(mvSys4);
3559     }
3560     if (distSurf)
3561     {
3562         device->DestroySurface2DUP(distSurf);
3563         CM_ALIGNED_FREE(distSys);
3564     }
3565     if (noiseAnalysisSurf)
3566     {
3567         device->DestroySurface2DUP(noiseAnalysisSurf);
3568         CM_ALIGNED_FREE(noiseAnalysisSys);
3569     }
3570 
3571     if (pSCD)
3572     {
3573         pSCD->Close();
3574         pSCD = nullptr;
3575     }
3576 }
3577