1 // Copyright (c) 2018-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 "asc.h"
22 #include "asc_defs.h"
23 #include "asc_cpu_dispatcher.h"
24 #include "libmfx_core_interface.h"
25 #include "genx_scd_gen8_isa.h"
26 #include "genx_scd_gen9_isa.h"
27 #include "genx_scd_gen11_isa.h"
28 #include "genx_scd_gen11lp_isa.h"
29 #include "genx_scd_gen12lp_isa.h"
30 
31 #include "tree.h"
32 #include "iofunctions.h"
33 #include "motion_estimation_engine.h"
34 #include <limits.h>
35 #include <algorithm>
36 #include <cmath>
37 
38 using std::min;
39 using std::max;
40 
41 namespace ns_asc {
42 static mfxI8
43     PDISTTbl2[NumTSC*NumSC] =
44 {
45     2, 3, 3, 4, 4, 5, 5, 5, 5, 5,
46     2, 2, 3, 3, 4, 4, 5, 5, 5, 5,
47     1, 2, 2, 3, 3, 3, 4, 4, 5, 5,
48     1, 1, 2, 2, 3, 3, 3, 4, 4, 5,
49     1, 1, 2, 2, 3, 3, 3, 3, 3, 4,
50     1, 1, 1, 2, 2, 3, 3, 3, 3, 3,
51     1, 1, 1, 1, 2, 2, 3, 3, 3, 3,
52     1, 1, 1, 1, 2, 2, 2, 3, 3, 3,
53     1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
54     1, 1, 1, 1, 1, 1, 1, 1, 1, 1
55 };
56 static mfxU32 lmt_sc2[NumSC] = { 112, 255, 512, 1536, 4096, 6144, 10752, 16384, 23040, UINT_MAX };
57 static mfxU32 lmt_tsc2[NumTSC] = { 24, 48, 72, 96, 128, 160, 192, 224, 256, UINT_MAX };
58 
ASCimageData()59 ASC_API ASCimageData::ASCimageData() {
60     Image.data = nullptr;
61     Image.Y = nullptr;
62     Image.U = nullptr;
63     Image.V = nullptr;
64     Image.extHeight = 0;
65     Image.extWidth = 0;
66     Image.hBorder = 0;
67     Image.wBorder = 0;
68     Image.height = 0;
69     Image.width = 0;
70     Image.pitch = 0;
71 
72     pInteger = nullptr;
73     gpuImage = nullptr;
74     idxImage = nullptr;
75     Cs = nullptr;
76     Rs = nullptr;
77     RsCs = nullptr;
78     SAD = nullptr;
79 
80     CsVal = 0;
81     RsVal = 0;
82     avgval = 0;
83     var = 0;
84     jtvar = 0;
85     mcjtvar = 0;
86     tcor = 0;
87     mcTcor = 0;
88 }
89 
InitFrame(ASCImDetails * pDetails)90 mfxStatus ASCimageData::InitFrame(ASCImDetails *pDetails) {
91     mfxU32
92         imageSpaceSize = pDetails->Extended_Height * pDetails->Extended_Width,
93         mvSpaceSize = (pDetails->_cheight * pDetails->_cwidth) >> 6,
94         texSpaceSize = (pDetails->_cheight * pDetails->_cwidth) >> 4;
95 
96     Image.extHeight = pDetails->Extended_Height;
97     Image.extWidth = pDetails->Extended_Width;
98     Image.pitch = pDetails->Extended_Width;
99     Image.height = pDetails->_cheight;
100     Image.width = pDetails->_cwidth;
101     Image.hBorder = pDetails->vertical_pad;
102     Image.wBorder = pDetails->horizontal_pad;
103     Image.data = NULL;
104     Image.Y = NULL;
105     Image.U = NULL;
106     Image.V = NULL;
107     //Memory Allocation
108     Image.data = (mfxU8*)aligned_alloc(0x1000, imageSpaceSize);
109     SAD = (mfxU16 *)aligned_alloc(0x1000, sizeof(mfxU16) * mvSpaceSize);
110     Rs = (mfxU16 *)aligned_alloc(0x1000, sizeof(mfxU16) * texSpaceSize);
111     Cs = (mfxU16 *)aligned_alloc(0x1000, sizeof(mfxU16) * texSpaceSize);
112     RsCs = (mfxU16 *)aligned_alloc(0x1000, sizeof(mfxU16) * texSpaceSize);
113     pInteger = (ASCMVector *)aligned_alloc(0x1000, sizeof(ASCMVector)  * mvSpaceSize);
114     if (Image.data == NULL)
115         return MFX_ERR_MEMORY_ALLOC;
116     //Pointer conf.
117     memset(Image.data, 0, sizeof(mfxU8) * imageSpaceSize);
118     Image.Y = Image.data + pDetails->initial_point;
119     if (SAD == NULL || Rs == NULL)
120         return MFX_ERR_MEMORY_ALLOC;
121     memset(Rs, 0, sizeof(mfxU16) * texSpaceSize);
122     if (Cs == NULL)
123         return MFX_ERR_MEMORY_ALLOC;
124     memset(Cs, 0, sizeof(mfxU16) * texSpaceSize);
125     if (RsCs == NULL)
126         return MFX_ERR_MEMORY_ALLOC;
127     memset(RsCs, 0, sizeof(mfxU16) * texSpaceSize);
128     if (pInteger == NULL)
129         return MFX_ERR_MEMORY_ALLOC;
130     memset(pInteger, 0, sizeof(ASCMVector)  * mvSpaceSize);
131     return MFX_ERR_NONE;
132 }
133 
InitAuxFrame(ASCImDetails * pDetails)134 mfxStatus ASCimageData::InitAuxFrame(ASCImDetails *pDetails) {
135     mfxU32
136         imageSpaceSize = pDetails->Extended_Height * pDetails->Extended_Width;
137 
138     Image.extHeight = pDetails->Extended_Height;
139     Image.extWidth = pDetails->Extended_Width;
140     Image.pitch = pDetails->Extended_Width;
141     Image.height = pDetails->_cheight;
142     Image.width = pDetails->_cwidth;
143     Image.hBorder = pDetails->vertical_pad;
144     Image.wBorder = pDetails->horizontal_pad;
145     Image.data = NULL;
146     Image.Y = NULL;
147     Image.U = NULL;
148     Image.V = NULL;
149     //Memory Allocation
150     Image.data = (mfxU8*)aligned_alloc(0x1000, imageSpaceSize);
151     if (Image.data == NULL)
152         return MFX_ERR_MEMORY_ALLOC;
153     //Pointer conf.
154     memset(Image.data, 0, sizeof(mfxU8) * imageSpaceSize);
155     Image.Y = Image.data + pDetails->initial_point;
156     return MFX_ERR_NONE;
157 }
158 
Close()159 void ASCimageData::Close() {
160     if (Rs)
161         free(Rs);
162     if (Cs)
163         free(Cs);
164     if (RsCs)
165         free(RsCs);
166     if (pInteger)
167         free(pInteger);
168     if (SAD)
169         free(SAD);
170     if (Image.data)
171         free(Image.data);
172     Rs = nullptr;
173     Cs = nullptr;
174     RsCs = nullptr;
175     pInteger = nullptr;
176     SAD = nullptr;
177     Image.data = nullptr;
178     Image.Y = nullptr;
179     Image.U = nullptr;
180     Image.V = nullptr;
181 }
182 
ASC()183 ASC_API ASC::ASC()
184 {
185     m_device = nullptr;
186     m_queue  = nullptr;
187     m_pSurfaceCp = nullptr;
188     m_pIdxSurfCp = nullptr;
189     m_program    = nullptr;
190     m_kernel_p = nullptr;
191     m_kernel_t = nullptr;
192     m_kernel_b = nullptr;
193     m_kernel_cp = nullptr;
194     m_threadSpace = nullptr,
195     m_threadSpaceCp = nullptr;
196     m_subSamplingEv = nullptr;
197     m_frameCopyEv   = nullptr;
198     m_task = nullptr,
199     m_taskCp = nullptr;
200 
201     m_gpuImPitch = 0;
202     m_threadsWidth = 0;
203     m_threadsHeight = 0;
204     m_gpuwidth = 0,
205     m_gpuheight = 0;
206 
207     m_frameBkp = nullptr;
208     m_support  = nullptr;
209     m_dataIn   = nullptr;
210     m_videoData = nullptr;
211 
212     m_dataReady = false;
213     m_cmDeviceAssigned = false;
214     m_is_LTR_on = false;
215     m_ASCinitialized = false;
216 
217     m_width = 0;
218     m_height = 0;
219     m_pitch = 0;
220 
221     m_AVX2_available = 0;
222     m_SSE4_available = 0;
223     GainOffset              = nullptr;
224     RsCsCalc_4x4            = nullptr;
225     RsCsCalc_bound          = nullptr;
226     RsCsCalc_diff           = nullptr;
227     ImageDiffHistogram      = nullptr;
228     ME_SAD_8x8_Block_Search = nullptr;
229     Calc_RaCa_pic           = nullptr;
230     resizeFunc              = nullptr;
231     ME_SAD_8x8_Block        = nullptr;
232     ME_VAR_8x8_Block        = nullptr;
233 }
234 
Setup_Environment()235 void ASC::Setup_Environment() {
236     m_dataIn->accuracy = 1;
237 
238     m_dataIn->layer->Original_Width = ASC_SMALL_WIDTH;
239     m_dataIn->layer->Original_Height = ASC_SMALL_HEIGHT;
240     m_dataIn->layer->_cwidth = ASC_SMALL_WIDTH;
241     m_dataIn->layer->_cheight = ASC_SMALL_HEIGHT;
242 
243     m_dataIn->layer->block_width = 8;
244     m_dataIn->layer->block_height = 8;
245     m_dataIn->layer->vertical_pad = 0;
246     m_dataIn->layer->horizontal_pad = 0;
247     m_dataIn->layer->Extended_Height = m_dataIn->layer->vertical_pad + ASC_SMALL_HEIGHT + m_dataIn->layer->vertical_pad;
248     m_dataIn->layer->Extended_Width = m_dataIn->layer->horizontal_pad + ASC_SMALL_WIDTH + m_dataIn->layer->horizontal_pad;
249     m_dataIn->layer->pitch = m_dataIn->layer->Extended_Width;
250     m_dataIn->layer->Height_in_blocks = m_dataIn->layer->_cheight / m_dataIn->layer->block_height;
251     m_dataIn->layer->Width_in_blocks = m_dataIn->layer->_cwidth / m_dataIn->layer->block_width;
252     m_dataIn->layer->sidesize = m_dataIn->layer->_cheight + (1 * m_dataIn->layer->vertical_pad);
253     m_dataIn->layer->initial_point = (m_dataIn->layer->Extended_Width * m_dataIn->layer->vertical_pad) + m_dataIn->layer->horizontal_pad;
254     m_dataIn->layer->MVspaceSize = (m_dataIn->layer->_cheight / m_dataIn->layer->block_height) * (m_dataIn->layer->_cwidth / m_dataIn->layer->block_width);
255 }
256 
Reset_ASCCmDevice()257 void ASC::Reset_ASCCmDevice() {
258     m_cmDeviceAssigned = false;
259 }
260 
Set_ASCCmDevice()261 void ASC::Set_ASCCmDevice() {
262     m_cmDeviceAssigned = true;
263 }
264 
Query_ASCCmDevice()265 bool ASC::Query_ASCCmDevice() {
266     return m_cmDeviceAssigned;
267 }
268 
InitGPUsurf(CmDevice * pCmDevice)269 mfxStatus ASC::InitGPUsurf(CmDevice* pCmDevice) {
270 #ifdef MFX_ENABLE_KERNELS
271     INT res = CM_SUCCESS;
272     m_subSamplingEv = nullptr;
273     m_frameCopyEv   = nullptr;
274 
275     Reset_ASCCmDevice();
276     m_device = pCmDevice;
277     if (!m_device)
278         res = CM_FAILURE;
279 
280     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
281     Set_ASCCmDevice();
282 
283     res = m_device->CreateQueue(m_queue);
284     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
285 
286     mfxU32 hwType = 0;
287     size_t hwSize = sizeof(hwType);
288     res = m_device->GetCaps(CAP_GPU_PLATFORM, hwSize, &hwType);
289     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
290 
291     switch (hwType)
292     {
293     case PLATFORM_INTEL_BDW:
294         res = m_device->LoadProgram((void *)genx_scd_gen8, sizeof(genx_scd_gen8), m_program, "nojitter");
295         break;
296     case PLATFORM_INTEL_SKL:
297     case PLATFORM_INTEL_KBL:
298     case PLATFORM_INTEL_CFL:
299     case PLATFORM_INTEL_GLK:
300     case PLATFORM_INTEL_BXT:
301         res = m_device->LoadProgram((void *)genx_scd_gen9, sizeof(genx_scd_gen9), m_program, "nojitter");
302         break;
303     case PLATFORM_INTEL_ICL:
304         res = m_device->LoadProgram((void *)genx_scd_gen11, sizeof(genx_scd_gen11), m_program, "nojitter");
305         break;
306     case PLATFORM_INTEL_ICLLP:
307         res = m_device->LoadProgram((void *)genx_scd_gen11lp, sizeof(genx_scd_gen11lp), m_program, "nojitter");
308         break;
309     case PLATFORM_INTEL_TGLLP:
310     case PLATFORM_INTEL_RKL:
311     case PLATFORM_INTEL_DG1:
312         res = m_device->LoadProgram((void *)genx_scd_gen12lp, sizeof(genx_scd_gen12lp), m_program, "nojitter");
313         break;
314     default:
315         res = CM_NOT_IMPLEMENTED;
316 }
317     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
318 
319     return MFX_ERR_NONE;
320 #else
321     (void)pCmDevice;
322     return MFX_ERR_UNSUPPORTED;
323 #endif
324 }
325 
Params_Init()326 void ASC::Params_Init() {
327     m_dataIn->accuracy  = 1;
328     m_dataIn->processed_frames = 0;
329     m_dataIn->total_number_of_frames = -1;
330     m_dataIn->starting_frame = 0;
331     m_dataIn->key_frame_frequency = INT_MAX;
332     m_dataIn->limitRange = 0;
333     m_dataIn->maxXrange = 32;
334     m_dataIn->maxYrange = 32;
335     m_dataIn->interlaceMode = 0;
336     m_dataIn->StartingField = ASCTopField;
337     m_dataIn->currentField = ASCTopField;
338     ImDetails_Init(m_dataIn->layer);
339 }
340 
CreateCmKernels()341 mfxStatus ASC::CreateCmKernels() {
342     INT res;
343     m_kernel_p = NULL;
344     m_kernel_t = NULL;
345     m_kernel_b = NULL;
346     m_threadSpace = NULL;
347     m_threadSpaceCp = NULL;
348 
349     m_threadsWidth = subWidth / OUT_BLOCK;
350     m_threadsHeight = subHeight;
351 
352     res = m_device->CreateThreadSpace(m_threadsWidth, m_threadsHeight, m_threadSpace);
353     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
354     res = m_device->CreateKernel(m_program, CM_KERNEL_FUNCTION(SubSamplePoint_p), m_kernel_p);
355     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
356     res = m_kernel_p->SetThreadCount(m_threadsWidth * m_threadsHeight);
357     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
358     res = m_device->CreateKernel(m_program, CM_KERNEL_FUNCTION(SubSamplePoint_t), m_kernel_t);
359     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
360     res = m_kernel_t->SetThreadCount(m_threadsWidth * m_threadsHeight);
361     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
362     res = m_device->CreateKernel(m_program, CM_KERNEL_FUNCTION(SubSamplePoint_b), m_kernel_b);
363     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
364     res = m_kernel_b->SetThreadCount(m_threadsWidth * m_threadsHeight);
365     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
366 #ifndef CMRT_EMU
367     res = m_kernel_p->AssociateThreadSpace(m_threadSpace);
368     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
369     res = m_kernel_t->AssociateThreadSpace(m_threadSpace);
370     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
371     res = m_kernel_b->AssociateThreadSpace(m_threadSpace);
372     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
373 #endif
374     return MFX_ERR_NONE;
375 }
376 
SetInterlaceMode(ASCFTS interlaceMode)377 ASC_API mfxStatus ASC::SetInterlaceMode(ASCFTS interlaceMode) {
378     if (interlaceMode > ASCbotfieldFirst_frame) {
379         ASC_PRINTF("\nError: Interlace Mode invalid, valid values are: 1 (progressive), 2 (TFF), 3 (BFF)\n");
380         return MFX_ERR_INVALID_VIDEO_PARAM;
381     }
382     else
383         m_dataIn->interlaceMode = interlaceMode;
384 
385     m_dataIn->StartingField = ASCTopField;
386     if (m_dataIn->interlaceMode != ASCprogressive_frame) {
387         if (m_dataIn->interlaceMode == ASCbotfieldFirst_frame)
388             m_dataIn->StartingField = ASCBottomField;
389         resizeFunc = &ASC::SubSampleASC_ImageInt;
390     }
391     else {
392         resizeFunc = &ASC::SubSampleASC_ImagePro;
393     }
394     m_dataIn->currentField = m_dataIn->StartingField;
395     return MFX_ERR_NONE;
396 }
397 
VidSample_Alloc()398 mfxStatus ASC::VidSample_Alloc() {
399     INT res = CM_SUCCESS;
400 
401     for (mfxI32 i = 0; i < ASCVIDEOSTATSBUF; i++)
402     {
403         MFX_SAFE_CALL(m_videoData[i]->layer.InitFrame(m_dataIn->layer));
404         if (Query_ASCCmDevice())
405         {
406             res = m_device->CreateSurface2DUP(m_dataIn->layer->Extended_Width, m_dataIn->layer->Extended_Height, CM_SURFACE_FORMAT_A8, (void *)m_videoData[i]->layer.Image.data, m_videoData[i]->layer.gpuImage);
407             SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
408             res = m_videoData[i]->layer.gpuImage->GetIndex(m_videoData[i]->layer.idxImage);
409             SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
410         }
411         else
412         {
413             m_videoData[i]->layer.gpuImage = nullptr;
414             m_videoData[i]->layer.idxImage = nullptr;
415         }
416     }
417 
418     if (Query_ASCCmDevice())
419     {
420         mfxU32
421             physicalSize = 0;
422         res = m_device->GetSurface2DInfo(m_gpuwidth, m_gpuheight, CM_SURFACE_FORMAT_NV12, m_gpuImPitch, physicalSize);
423         SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
424         m_frameBkp = nullptr;
425         m_frameBkp = (mfxU8*)aligned_alloc(0x1000, physicalSize);
426         if (m_frameBkp == nullptr)
427             return MFX_ERR_MEMORY_ALLOC;
428         memset(m_frameBkp, 0, physicalSize);
429         res = m_device->CreateSurface2DUP(m_gpuImPitch, m_gpuheight, CM_SURFACE_FORMAT_NV12, (void *)m_frameBkp, m_pSurfaceCp);
430         SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
431         res = m_pSurfaceCp->GetIndex(m_pIdxSurfCp);
432         SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
433     }
434     else
435     {
436         m_frameBkp = nullptr;
437         m_pSurfaceCp = nullptr;
438         m_pIdxSurfCp = nullptr;
439     }
440     return MFX_ERR_NONE;
441 }
442 
AssignResources(mfxU8 position,mfxU8 * pixelData)443 mfxStatus ASC::AssignResources(mfxU8 position, mfxU8 *pixelData)
444 {
445     if (!IsASCinitialized())
446         return MFX_ERR_DEVICE_FAILED;
447     if (pixelData == nullptr)
448         return MFX_ERR_DEVICE_FAILED;
449     m_videoData[position]->layer.Image.Y = pixelData;
450     return MFX_ERR_NONE;
451 }
452 
AssignResources(mfxU8 position,CmSurface2DUP * inputFrame,mfxU8 * pixelData)453 mfxStatus ASC::AssignResources(mfxU8 position, CmSurface2DUP *inputFrame, mfxU8 *pixelData)
454 {
455     if (!IsASCinitialized())
456         return MFX_ERR_DEVICE_FAILED;
457     if (inputFrame == nullptr)
458         return MFX_ERR_DEVICE_FAILED;
459     //std::swap(m_videoData[position]->layer.gpuImage, inputFrame);
460     m_videoData[position]->layer.gpuImage = inputFrame;
461     m_videoData[position]->layer.gpuImage->GetIndex(m_videoData[position]->layer.idxImage);
462     if (pixelData == nullptr)
463         return MFX_ERR_DEVICE_FAILED;
464     /*std::swap(m_videoData[position]->layer.Image.data, pixelData);
465     m_videoData[position]->layer.Image.Y = m_videoData[position]->layer.Image.data;*/
466     m_videoData[position]->layer.Image.Y = pixelData;
467     return MFX_ERR_NONE;
468 }
469 
SwapResources(mfxU8 position,CmSurface2DUP ** inputFrame,mfxU8 ** pixelData)470 mfxStatus ASC::SwapResources(mfxU8 position, CmSurface2DUP **inputFrame, mfxU8 **pixelData)
471 {
472     if (!IsASCinitialized())
473         return MFX_ERR_DEVICE_FAILED;
474     if (inputFrame == nullptr)
475         return MFX_ERR_DEVICE_FAILED;
476     std::swap(m_videoData[position]->layer.gpuImage, *inputFrame);
477     m_videoData[position]->layer.gpuImage->GetIndex(m_videoData[position]->layer.idxImage);
478     if (pixelData == nullptr)
479         return MFX_ERR_DEVICE_FAILED;
480     std::swap(m_videoData[position]->layer.Image.data, *pixelData);
481     m_videoData[position]->layer.Image.Y = m_videoData[position]->layer.Image.data;
482     return MFX_ERR_NONE;
483 }
484 
VidSample_dispose()485 void ASC::VidSample_dispose()
486 {
487     for (mfxI32 i = ASCVIDEOSTATSBUF - 1; i >= 0; i--)
488     {
489         if (m_videoData[i] != nullptr)
490         {
491             m_videoData[i]->layer.Close();
492             if (m_videoData[i]->layer.gpuImage) {
493                 m_device->DestroySurface2DUP(m_videoData[i]->layer.gpuImage);
494                 m_videoData[i]->layer.gpuImage = nullptr;
495                 m_videoData[i]->layer.idxImage = nullptr;
496             }
497             delete (m_videoData[i]);
498         }
499     }
500     free(m_frameBkp);
501 }
VidRead_dispose()502 void ASC::VidRead_dispose()
503 {
504     if (m_support->logic != nullptr)
505     {
506         for (mfxI32 i = 0; i < TSCSTATBUFFER; i++)
507             delete m_support->logic[i];
508         delete[] m_support->logic;
509     }
510     if (m_support->gainCorrection.Image.data != nullptr)
511         m_support->gainCorrection.Close();
512 }
513 
alloc()514 mfxStatus ASC::alloc() {
515     return VidSample_Alloc();
516 }
517 
InitCPU()518 mfxStatus ASC::InitCPU() {
519     return alloc();
520 }
521 
IO_Setup()522 mfxStatus ASC::IO_Setup() {
523     mfxStatus sts = MFX_ERR_NONE;
524     sts = alloc();
525     SCD_CHECK_MFX_ERR(sts);
526     if (Query_ASCCmDevice())
527     {
528         SCD_CHECK_CM_ERR(m_device->CreateKernel(m_program, CM_KERNEL_FUNCTION(surfaceCopy_Y), m_kernel_cp), MFX_ERR_DEVICE_FAILED);
529         m_threadsWidth = (UINT)ceil((double)m_gpuwidth / SCD_BLOCK_PIXEL_WIDTH);
530         m_threadsHeight = (UINT)ceil((double)m_gpuheight / SCD_BLOCK_HEIGHT);
531         SCD_CHECK_CM_ERR(m_device->CreateThreadSpace(m_threadsWidth, m_threadsHeight, m_threadSpaceCp), MFX_ERR_DEVICE_FAILED);
532         SCD_CHECK_CM_ERR(m_kernel_cp->SetThreadCount(m_threadsWidth * m_threadsHeight), MFX_ERR_DEVICE_FAILED);
533 #ifndef CMRT_EMU
534         SCD_CHECK_CM_ERR(m_kernel_cp->AssociateThreadSpace(m_threadSpaceCp), MFX_ERR_DEVICE_FAILED);
535 #endif
536     }
537     else
538     {
539         m_kernel_cp = nullptr;
540         m_threadSpaceCp = nullptr;
541     }
542     return sts;
543 }
544 
InitStruct()545 void ASC::InitStruct() {
546     m_dataIn = nullptr;
547     m_support = nullptr;
548     m_videoData = nullptr;
549     resizeFunc = nullptr;
550 }
551 
VidRead_Init()552 mfxStatus ASC::VidRead_Init() {
553     mfxStatus sts = MFX_ERR_NONE;
554     m_support->control                 = 0;
555     m_support->average                 = 0;
556     m_support->avgSAD                  = 0;
557     m_support->gopSize                 = 1;
558     m_support->pendingSch              = 0;
559     m_support->lastSCdetectionDistance = 0;
560     m_support->detectedSch             = 0;
561     m_support->frameOrder              = 0;
562     m_support->PDistanceTable            = PDISTTbl2;
563     m_support->size                      = ASCSmall_Size;
564     m_support->firstFrame                = true;
565     m_support->gainCorrection.Image.data = nullptr;
566     m_support->gainCorrection.Image.Y    = nullptr;
567     m_support->gainCorrection.Image.U    = nullptr;
568     m_support->gainCorrection.Image.V    = nullptr;
569     m_support->gainCorrection.Cs         = nullptr;
570     m_support->gainCorrection.Rs         = nullptr;
571     m_support->gainCorrection.RsCs       = nullptr;
572     m_support->gainCorrection.pInteger   = nullptr;
573     m_support->gainCorrection.SAD        = nullptr;
574     try
575     {
576         m_support->logic = new ASCTSCstat *[TSCSTATBUFFER];
577     }
578     catch (...)
579     {
580         return MFX_ERR_MEMORY_ALLOC;
581     }
582     sts = ASCTSCstat_Init(m_support->logic);
583     SCD_CHECK_MFX_ERR(sts);
584 //#if USE_SCD
585     sts = m_support->gainCorrection.InitAuxFrame(m_dataIn->layer);
586 //#else
587 //    sts = m_support->gainCorrection.InitFrame(m_dataIn->layer);
588 //#endif
589     SCD_CHECK_MFX_ERR(sts);
590     return sts;
591 }
592 
VidSample_Init()593 void ASC::VidSample_Init() {
594     for(mfxI32 i = 0; i < ASCVIDEOSTATSBUF; i++) {
595         nullifier(&m_videoData[i]->layer);
596         imageInit(&m_videoData[i]->layer.Image);
597         m_videoData[i]->frame_number = -1;
598         m_videoData[i]->forward_reference = -1;
599         m_videoData[i]->backward_reference = -1;
600     }
601 }
602 
SetUltraFastDetection()603 void ASC::SetUltraFastDetection() {
604     m_support->size = ASCSmall_Size;
605     resizeFunc = &ASC::SubSampleASC_ImagePro;
606 }
607 
SetWidth(mfxI32 Width)608 mfxStatus ASC::SetWidth(mfxI32 Width) {
609     if(Width < ASC_SMALL_WIDTH) {
610         ASC_PRINTF("\nError: Width value is too small, it needs to be bigger than %i\n", ASC_SMALL_WIDTH);
611         return MFX_ERR_UNSUPPORTED;
612     }
613     else
614         m_width = Width;
615 
616     return MFX_ERR_NONE;
617 }
618 
SetHeight(mfxI32 Height)619 mfxStatus ASC::SetHeight(mfxI32 Height) {
620     if(Height < ASC_SMALL_HEIGHT) {
621         ASC_PRINTF("\nError: Height value is too small, it needs to be bigger than %i\n", ASC_SMALL_HEIGHT);
622         return MFX_ERR_UNSUPPORTED;
623     }
624     else
625         m_height = Height;
626 
627     return MFX_ERR_NONE;
628 }
629 
SetPitch(mfxI32 Pitch)630 mfxStatus ASC::SetPitch(mfxI32 Pitch) {
631     if(m_width < ASC_SMALL_WIDTH) {
632         ASC_PRINTF("\nError: Width value has not been set, init the variables first\n");
633         return MFX_ERR_UNSUPPORTED;
634     }
635 
636     if(Pitch < m_width) {
637         ASC_PRINTF("\nError: Pitch value is too small, it needs to be bigger than %i\n", m_width);
638         return MFX_ERR_UNSUPPORTED;
639     }
640     else
641         m_pitch = Pitch;
642 
643     return MFX_ERR_NONE;
644 }
645 
SetNextField()646 void ASC::SetNextField() {
647     if(m_dataIn->interlaceMode != ASCprogressive_frame)
648         m_dataIn->currentField = !m_dataIn->currentField;
649 }
650 
SetDimensions(mfxI32 Width,mfxI32 Height,mfxI32 Pitch)651 mfxStatus ASC::SetDimensions(mfxI32 Width, mfxI32 Height, mfxI32 Pitch) {
652     mfxStatus sts;
653     sts = SetWidth(Width);
654     SCD_CHECK_MFX_ERR(sts);
655     sts = SetHeight(Height);
656     SCD_CHECK_MFX_ERR(sts);
657     sts = SetPitch(Pitch);
658     SCD_CHECK_MFX_ERR(sts);
659     return sts;
660 }
661 
662 
663 #define ASC_CPU_DISP_INIT_C(func)           (func = (func ## _C))
664 #define ASC_CPU_DISP_INIT_SSE4(func)        (func = (func ## _SSE4))
665 #define ASC_CPU_DISP_INIT_SSE4_C(func)      (m_SSE4_available ? ASC_CPU_DISP_INIT_SSE4(func) : ASC_CPU_DISP_INIT_C(func))
666 
667 #define ASC_CPU_DISP_INIT_AVX2(func)        (func = (func ## _AVX2))
668 #define ASC_CPU_DISP_INIT_AVX2_SSE4_C(func) (m_AVX2_available ? ASC_CPU_DISP_INIT_AVX2(func) : ASC_CPU_DISP_INIT_SSE4_C(func))
669 #define ASC_CPU_DISP_INIT_AVX2_C(func)      (m_AVX2_available ? ASC_CPU_DISP_INIT_AVX2(func) : ASC_CPU_DISP_INIT_C(func))
670 
Init(mfxI32 Width,mfxI32 Height,mfxI32 Pitch,mfxU32 PicStruct,CmDevice * pCmDevice)671 ASC_API mfxStatus ASC::Init(mfxI32 Width, mfxI32 Height, mfxI32 Pitch, mfxU32 PicStruct, CmDevice* pCmDevice)
672 {
673     mfxStatus sts = MFX_ERR_NONE;
674     INT res;
675     m_device = nullptr;
676     m_queue = nullptr;
677     m_program = nullptr;
678 
679     m_task = nullptr;
680     m_taskCp = nullptr;
681 
682     m_AVX2_available = CpuFeature_AVX2();
683     m_SSE4_available = CpuFeature_SSE41();
684 
685     if (!m_SSE4_available)
686         return MFX_ERR_UNSUPPORTED;
687 
688     ME_SAD_8x8_Block    = ME_SAD_8x8_Block_SSE4;
689     ME_VAR_8x8_Block    = ME_VAR_8x8_Block_SSE4;
690 
691     ASC_CPU_DISP_INIT_C(GainOffset);
692     ASC_CPU_DISP_INIT_SSE4_C(RsCsCalc_4x4);
693     ASC_CPU_DISP_INIT_C(RsCsCalc_bound);
694     ASC_CPU_DISP_INIT_C(RsCsCalc_diff);
695     ASC_CPU_DISP_INIT_SSE4_C(ImageDiffHistogram);
696     ASC_CPU_DISP_INIT_AVX2_SSE4_C(ME_SAD_8x8_Block_Search);
697     ASC_CPU_DISP_INIT_SSE4_C(Calc_RaCa_pic);
698 
699     InitStruct();
700     try
701     {
702         m_dataIn = new ASCVidData;
703     }
704     catch (...)
705     {
706         return MFX_ERR_MEMORY_ALLOC;
707     }
708     m_dataIn->layer = nullptr;
709     try
710     {
711         m_dataIn->layer = new ASCImDetails;
712         m_videoData = new ASCVidSample *[ASCVIDEOSTATSBUF];
713         for(mfxU8 i =0; i < ASCVIDEOSTATSBUF; i++)
714             m_videoData[i] = nullptr;
715         m_support = new ASCVidRead;
716     }
717     catch (...)
718     {
719         return MFX_ERR_MEMORY_ALLOC;
720     }
721 
722     if (pCmDevice)
723     {
724         res = InitGPUsurf(pCmDevice);
725         SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
726     }
727 
728     for (mfxI32 i = 0; i < ASCVIDEOSTATSBUF; i++)
729     {
730         try
731         {
732             m_videoData[i] = new ASCVidSample;
733         }
734         catch (...)
735         {
736             return MFX_ERR_MEMORY_ALLOC;
737         }
738     }
739     Params_Init();
740 
741     sts = SetDimensions(Width, Height, Pitch);
742     SCD_CHECK_MFX_ERR(sts);
743 
744     m_gpuwidth = Width;
745     m_gpuheight = Height;
746 
747     VidSample_Init();
748     Setup_Environment();
749 
750     sts = IO_Setup();
751     SCD_CHECK_MFX_ERR(sts);
752 
753     sts = VidRead_Init();
754     SCD_CHECK_MFX_ERR(sts);
755     SetUltraFastDetection();
756 
757     if (Query_ASCCmDevice()) {
758         sts = CreateCmKernels();
759         SCD_CHECK_MFX_ERR(sts);
760     }
761 
762     sts = SetInterlaceMode((PicStruct & MFX_PICSTRUCT_FIELD_TFF) ? ASCtopfieldfirst_frame :
763         (PicStruct & MFX_PICSTRUCT_FIELD_BFF) ? ASCbotfieldFirst_frame :
764         ASCprogressive_frame);
765     SCD_CHECK_MFX_ERR(sts);
766     m_dataReady = false;
767     m_ASCinitialized = (sts == MFX_ERR_NONE);
768     return sts;
769 }
770 
IsASCinitialized()771 ASC_API bool ASC::IsASCinitialized(){
772     return m_ASCinitialized;
773 }
774 
SetControlLevel(mfxU8 level)775 ASC_API void ASC::SetControlLevel(mfxU8 level) {
776     if(level >= RF_DECISION_LEVEL) {
777         ASC_PRINTF("\nWarning: Control level too high, shot change detection disabled! (%i)\n", level);
778         ASC_PRINTF("Control levels 0 to %i, smaller value means more sensitive detection\n", RF_DECISION_LEVEL);
779     }
780     m_support->control = level;
781 }
782 
SetGoPSize(mfxU32 GoPSize)783 ASC_API mfxStatus ASC::SetGoPSize(mfxU32 GoPSize) {
784     if (GoPSize > Double_HEVC_Gop) {
785         ASC_PRINTF("\nError: GoPSize is too big! (%i)\n", GoPSize);
786         return MFX_ERR_INVALID_VIDEO_PARAM;
787     }
788     else if (GoPSize == Forbidden_GoP) {
789         ASC_PRINTF("\nError: GoPSize value cannot be zero!\n");
790         return MFX_ERR_INVALID_VIDEO_PARAM;
791     }
792     else if (GoPSize > HEVC_Gop && GoPSize <= Double_HEVC_Gop) {
793         ASC_PRINTF("\nWarning: Your GoPSize is larger than usual! (%i)\n", GoPSize);
794         return MFX_ERR_INVALID_VIDEO_PARAM;
795     }
796     m_support->gopSize = GoPSize;
797     m_support->pendingSch = 0;
798 
799     return MFX_ERR_NONE;
800 }
801 
ResetGoPSize()802 ASC_API void ASC::ResetGoPSize() {
803     SetGoPSize(Immediate_GoP);
804 }
805 
Close()806 ASC_API void ASC::Close() {
807     if(m_videoData != nullptr) {
808         VidSample_dispose();
809         delete[] m_videoData;
810         m_videoData = nullptr;
811     }
812 
813     if(m_support != nullptr) {
814         VidRead_dispose();
815         delete m_support;
816         m_support = nullptr;
817     }
818 
819     if(m_dataIn != nullptr) {
820         delete m_dataIn->layer;
821         delete m_dataIn;
822         m_dataIn = nullptr;
823     }
824 
825     if (m_device) {
826         for (auto& surf : m_tableCmRelations2) {
827             CmSurface2D *temp = surf.second;
828             m_device->DestroySurface(temp);
829         }
830         m_tableCmRelations2.clear();
831         m_tableCmIndex2.clear();
832 
833         if (m_kernel_p)  m_device->DestroyKernel(m_kernel_p);
834         if (m_kernel_t)  m_device->DestroyKernel(m_kernel_t);
835         if (m_kernel_b)  m_device->DestroyKernel(m_kernel_b);
836         if (m_kernel_cp) m_device->DestroyKernel(m_kernel_cp);
837         if (m_program)   m_device->DestroyProgram(m_program);
838         if (m_pSurfaceCp) m_device->DestroySurface2DUP(m_pSurfaceCp);
839         if (m_threadSpace)   m_device->DestroyThreadSpace(m_threadSpace);
840         if (m_threadSpaceCp) m_device->DestroyThreadSpace(m_threadSpaceCp);
841         if (m_task) m_device->DestroyTask(m_task);
842         if (m_taskCp) m_device->DestroyTask(m_taskCp);
843     }
844 
845     m_pSurfaceCp = nullptr;
846     m_kernel_p  = nullptr;
847     m_kernel_t  = nullptr;
848     m_kernel_b  = nullptr;
849     m_kernel_cp = nullptr;
850     m_program   = nullptr;
851     m_device    = nullptr;
852     m_threadSpace   = nullptr;
853     m_threadSpaceCp = nullptr;
854 }
855 
SubSampleASC_ImagePro(mfxU8 * frame,mfxI32 srcWidth,mfxI32 srcHeight,mfxI32 inputPitch,ASCLayers dstIdx,mfxU32)856 void ASC::SubSampleASC_ImagePro(mfxU8 *frame, mfxI32 srcWidth, mfxI32 srcHeight, mfxI32 inputPitch, ASCLayers dstIdx, mfxU32 /*parity*/) {
857 
858     ASCImDetails *pIDetDst = &m_dataIn->layer[dstIdx];
859     mfxU8 *pDst = m_videoData[ASCCurrent_Frame]->layer.Image.Y;
860     mfxI16& avgLuma = m_videoData[ASCCurrent_Frame]->layer.avgval;
861 
862     mfxI32 dstWidth = pIDetDst->Original_Width;
863     mfxI32 dstHeight = pIDetDst->Original_Height;
864     mfxI32 dstPitch = pIDetDst->pitch;
865 
866     SubSample_Point(frame, srcWidth, srcHeight, inputPitch, pDst, dstWidth, dstHeight, dstPitch, avgLuma);
867 }
868 
SubSampleASC_ImageInt(mfxU8 * frame,mfxI32 srcWidth,mfxI32 srcHeight,mfxI32 inputPitch,ASCLayers dstIdx,mfxU32 parity)869 void ASC::SubSampleASC_ImageInt(mfxU8 *frame, mfxI32 srcWidth, mfxI32 srcHeight, mfxI32 inputPitch, ASCLayers dstIdx, mfxU32 parity) {
870 
871     ASCImDetails *pIDetDst = &m_dataIn->layer[dstIdx];
872     mfxU8 *pDst = m_videoData[ASCCurrent_Frame]->layer.Image.Y;
873     mfxI16 &avgLuma = m_videoData[ASCCurrent_Frame]->layer.avgval;
874 
875     mfxI32 dstWidth = pIDetDst->Original_Width;
876     mfxI32 dstHeight = pIDetDst->Original_Height;
877     mfxI32 dstPitch = pIDetDst->pitch;
878 
879     SubSample_Point(frame + (parity * inputPitch), srcWidth, srcHeight / 2, inputPitch * 2, pDst, dstWidth, dstHeight, dstPitch, avgLuma);
880 }
881 
882 //
883 // SubSample pSrc into pDst, using point-sampling of source pixels
884 // Corrects the position on odd lines in case the input video is
885 // interlaced
886 //
SubSample_Point(pmfxU8 pSrc,mfxU32 srcWidth,mfxU32 srcHeight,mfxU32 srcPitch,pmfxU8 pDst,mfxU32 dstWidth,mfxU32 dstHeight,mfxU32 dstPitch,mfxI16 & avgLuma)887 void ASC::SubSample_Point(
888     pmfxU8 pSrc, mfxU32 srcWidth, mfxU32 srcHeight, mfxU32 srcPitch,
889     pmfxU8 pDst, mfxU32 dstWidth, mfxU32 dstHeight, mfxU32 dstPitch,
890     mfxI16 &avgLuma) {
891     mfxI32 step_w = srcWidth / dstWidth;
892     mfxI32 step_h = srcHeight / dstHeight;
893 
894     mfxI32 need_correction = !(step_h % 2);
895     mfxI32 correction = 0;
896     mfxU32 sumAll = 0;
897     mfxI32 y = 0;
898 
899     for (y = 0; y < (mfxI32)dstHeight; y++) {
900         correction = (y % 2) & need_correction;
901         for (mfxI32 x = 0; x < (mfxI32)dstWidth; x++) {
902 
903             pmfxU8 ps = pSrc + ((y * step_h + correction) * srcPitch) + (x * step_w);
904             pmfxU8 pd = pDst + (y * dstPitch) + x;
905 
906             pd[0] = ps[0];
907             sumAll += ps[0];
908         }
909     }
910     avgLuma = (mfxI16)(sumAll >> 13);
911 }
912 
RsCsCalc()913 mfxStatus ASC::RsCsCalc() {
914     ASCYUV
915          *pFrame = &m_videoData[ASCCurrent_Frame]->layer.Image;
916     ASCImDetails
917         vidCar = m_dataIn->layer[0];
918     pmfxU8
919         ss = pFrame->Y;
920     mfxU32
921         hblocks = (pFrame->height >> BLOCK_SIZE_SHIFT) /*- 2*/,
922         wblocks = (pFrame->width >> BLOCK_SIZE_SHIFT) /*- 2*/;
923 
924     mfxI16
925         diff = m_videoData[ASCReference_Frame]->layer.avgval - m_videoData[ASCCurrent_Frame]->layer.avgval;
926     ss = m_videoData[ASCReference_Frame]->layer.Image.Y;
927     if (!m_support->firstFrame && abs(diff) >= GAINDIFF_THR) {
928         if (m_support->gainCorrection.Image.Y == nullptr)
929             return MFX_ERR_MEMORY_ALLOC;
930         GainOffset(&ss, &m_support->gainCorrection.Image.Y, (mfxU16)vidCar._cwidth, (mfxU16)vidCar._cheight, (mfxU16)vidCar.Extended_Width, diff);
931     }
932     ss = m_videoData[ASCCurrent_Frame]->layer.Image.Y;
933 
934     RsCsCalc_4x4(ss, pFrame->pitch, wblocks, hblocks, m_videoData[ASCCurrent_Frame]->layer.Rs, m_videoData[ASCCurrent_Frame]->layer.Cs);
935     RsCsCalc_bound(m_videoData[ASCCurrent_Frame]->layer.Rs, m_videoData[ASCCurrent_Frame]->layer.Cs, m_videoData[ASCCurrent_Frame]->layer.RsCs, &m_videoData[ASCCurrent_Frame]->layer.RsVal, &m_videoData[ASCCurrent_Frame]->layer.CsVal, wblocks, hblocks);
936     return MFX_ERR_NONE;
937 }
938 
Hint_LTR_op_on(mfxU32 SC,mfxU32 TSC)939 bool Hint_LTR_op_on(mfxU32 SC, mfxU32 TSC) {
940     bool ltr = TSC *TSC < (std::max(SC, 64u) / 12);
941     return ltr;
942 }
943 
ShotDetect(ASCimageData & Data,ASCimageData & DataRef,ASCImDetails & imageInfo,ASCTSCstat * current,ASCTSCstat * reference,mfxU8 controlLevel)944 mfxI32 ASC::ShotDetect(ASCimageData& Data, ASCimageData& DataRef, ASCImDetails& imageInfo, ASCTSCstat *current, ASCTSCstat *reference, mfxU8 controlLevel) {
945     pmfxU8
946         ssFrame = Data.Image.Y,
947         refFrame = DataRef.Image.Y;
948     pmfxU16
949         objRs = Data.Rs,
950         objCs = Data.Cs,
951         refRs = DataRef.Rs,
952         refCs = DataRef.Cs;
953 
954     current->RsCsDiff = 0;
955     current->Schg = -1;
956     current->Gchg = 0;
957 
958     RsCsCalc_diff(objRs, objCs, refRs, refCs, 2*imageInfo.Width_in_blocks, 2*imageInfo.Height_in_blocks, &current->RsDiff, &current->CsDiff);
959     ImageDiffHistogram(ssFrame, refFrame, imageInfo.Extended_Width, imageInfo._cwidth, imageInfo._cheight, current->histogram, &current->ssDCint, &current->refDCint);
960 
961     if(reference->Schg)
962         current->last_shot_distance = 1;
963     else
964         current->last_shot_distance++;
965 
966     current->RsDiff >>= 9;
967     current->CsDiff >>= 9;
968     current->RsCsDiff      = (current->RsDiff*current->RsDiff)  + (current->CsDiff*current->CsDiff);
969     current->ssDCval       = (mfxI32)current->ssDCint >> 13;
970     current->refDCval      = (mfxI32)current->refDCint >> 13;
971     current->gchDC         = NABS(current->ssDCval - current->refDCval);
972     current->posBalance    = (current->histogram[3] + current->histogram[4]) >> 6;
973     current->negBalance    = (current->histogram[0] + current->histogram[1]) >> 6;
974     current->diffAFD       = current->AFD - reference->AFD;
975     current->diffTSC       = current->TSC - reference->TSC;
976     current->diffRsCsDiff  = current->RsCsDiff - reference->RsCsDiff;
977     current->diffMVdiffVal = current->MVdiffVal - reference->MVdiffVal;
978     mfxI32
979         SChange = SCDetectRF(
980             current->diffMVdiffVal, current->RsCsDiff,   current->MVdiffVal,
981             current->Rs,            current->AFD,        current->CsDiff,
982             current->diffTSC,       current->TSC,        current->gchDC,
983             current->diffRsCsDiff,  current->posBalance, current->SC,
984             current->TSCindex,      current->SCindex,    current->Cs,
985             current->diffAFD,       current->negBalance, current->ssDCval,
986             current->refDCval,      current->RsDiff,     controlLevel);
987 
988     current->ltr_flag = Hint_LTR_op_on(current->SC, current->TSC);
989     return SChange;
990 }
991 
MotionAnalysis(ASCVidSample * videoIn,ASCVidSample * videoRef,mfxU32 * TSC,mfxU16 * AFD,mfxU32 * MVdiffVal,mfxU32 * AbsMVSize,mfxU32 * AbsMVHSize,mfxU32 * AbsMVVSize,ASCLayers lyrIdx)992 void ASC::MotionAnalysis(ASCVidSample *videoIn, ASCVidSample *videoRef, mfxU32 *TSC, mfxU16 *AFD, mfxU32 *MVdiffVal, mfxU32 *AbsMVSize, mfxU32 *AbsMVHSize, mfxU32 *AbsMVVSize, ASCLayers lyrIdx) {
993     mfxU32//24bit is enough
994         valb = 0;
995     mfxU32
996         acc = 0;
997     /*--Motion Estimation--*/
998     *MVdiffVal = 0;
999     *AbsMVSize = 0;
1000     *AbsMVHSize = 0;
1001     *AbsMVVSize = 0;
1002     mfxI16
1003         diff = (int)videoIn->layer.avgval - (int)videoRef->layer.avgval;
1004 
1005     ASCimageData
1006         *referenceImageIn = &videoRef->layer;
1007 
1008     if (abs(diff) >= GAINDIFF_THR) {
1009         referenceImageIn = &m_support->gainCorrection;
1010     }
1011     m_support->average = 0;
1012     videoIn->layer.var = 0;
1013     videoIn->layer.jtvar = 0;
1014     videoIn->layer.mcjtvar = 0;
1015     for (mfxU16 i = 0; i < m_dataIn->layer[lyrIdx].Height_in_blocks; i++) {
1016         mfxU16 prevFPos = i << 4;
1017         for (mfxU16 j = 0; j < m_dataIn->layer[lyrIdx].Width_in_blocks; j++) {
1018             mfxU16 fPos = prevFPos + j;
1019             acc += ME_simple(m_support, fPos, m_dataIn->layer, &videoIn->layer, referenceImageIn, true, m_dataIn, ME_SAD_8x8_Block_Search, ME_SAD_8x8_Block, ME_VAR_8x8_Block);
1020             valb += videoIn->layer.SAD[fPos];
1021             *MVdiffVal += (videoIn->layer.pInteger[fPos].x - videoRef->layer.pInteger[fPos].x) * (videoIn->layer.pInteger[fPos].x - videoRef->layer.pInteger[fPos].x);
1022             *MVdiffVal += (videoIn->layer.pInteger[fPos].y - videoRef->layer.pInteger[fPos].y) * (videoIn->layer.pInteger[fPos].y - videoRef->layer.pInteger[fPos].y);
1023             *AbsMVHSize += (videoIn->layer.pInteger[fPos].x * videoIn->layer.pInteger[fPos].x);
1024             *AbsMVVSize += (videoIn->layer.pInteger[fPos].y * videoIn->layer.pInteger[fPos].y);
1025             *AbsMVSize += (videoIn->layer.pInteger[fPos].x * videoIn->layer.pInteger[fPos].x) + (videoIn->layer.pInteger[fPos].y * videoIn->layer.pInteger[fPos].y);
1026 
1027         }
1028     }
1029     videoIn->layer.var = videoIn->layer.var * 10 / 128 / 64;
1030     videoIn->layer.jtvar = videoIn->layer.jtvar * 10 / 128 / 64;
1031     videoIn->layer.mcjtvar = videoIn->layer.mcjtvar * 10 / 128 / 64;
1032     if (videoIn->layer.var == 0)
1033     {
1034         if (videoIn->layer.jtvar == 0)
1035             videoIn->layer.tcor = 100;
1036         else
1037             videoIn->layer.tcor = (mfxI16)NMIN(1000 * videoIn->layer.jtvar, 2000);
1038 
1039         if (videoIn->layer.mcjtvar == 0)
1040             videoIn->layer.mcTcor = 100;
1041         else
1042             videoIn->layer.mcTcor = (mfxI16)NMIN(1000 * videoIn->layer.mcjtvar, 2000);
1043     }
1044     else
1045     {
1046         videoIn->layer.tcor = (mfxI16)(100 * videoIn->layer.jtvar / videoIn->layer.var);
1047         videoIn->layer.mcTcor = (mfxI16)(100 * videoIn->layer.mcjtvar / videoIn->layer.var);
1048     }
1049     *TSC = valb >> 8;
1050     *AFD = (mfxU16)(acc >> 13);//Picture area is 2^13, and 10 have been done before so it needs to shift 3 more.
1051     *MVdiffVal = *MVdiffVal >> 7;
1052 }
1053 
TableLookUp(mfxU32 limit,mfxU32 * table,mfxU32 comparisonValue)1054 mfxU32 TableLookUp(mfxU32 limit, mfxU32 *table, mfxU32 comparisonValue) {
1055     for (mfxU32 pos = 0; pos < limit; pos++) {
1056         if (comparisonValue < table[pos])
1057             return pos;
1058     }
1059     return limit;
1060 }
1061 
CorrectionForGoPSize(ASCVidRead * m_support,mfxU32 PdIndex)1062 void CorrectionForGoPSize(ASCVidRead *m_support, mfxU32 PdIndex) {
1063     m_support->detectedSch = 0;
1064     if(m_support->logic[PdIndex]->Schg) {
1065         if(m_support->lastSCdetectionDistance % m_support->gopSize)
1066             m_support->pendingSch = 1;
1067         else {
1068             m_support->lastSCdetectionDistance = 0;
1069             m_support->pendingSch = 0;
1070             m_support->detectedSch = 1;
1071         }
1072     }
1073     else if(m_support->pendingSch) {
1074         if(!(m_support->lastSCdetectionDistance % m_support->gopSize)) {
1075             m_support->lastSCdetectionDistance = 0;
1076             m_support->pendingSch = 0;
1077             m_support->detectedSch = 1;
1078         }
1079     }
1080     m_support->lastSCdetectionDistance++;
1081 }
1082 
CompareStats(mfxU8 current,mfxU8 reference)1083 bool ASC::CompareStats(mfxU8 current, mfxU8 reference) {
1084     if (current > 2 || reference > 2 || current == reference) {
1085         ASC_PRINTF("Error: Invalid stats comparison\n");
1086         assert(!"Error: Invalid stats comparison");
1087     }
1088     mfxU8 comparison = 0;
1089     if (m_dataIn->interlaceMode == ASCprogressive_frame) {
1090         comparison += m_support->logic[current]->AFD == 0;
1091         comparison += m_support->logic[current]->RsCsDiff == 0;
1092         comparison += m_support->logic[current]->TSCindex == 0;
1093         comparison += m_support->logic[current]->negBalance <= 3;
1094         comparison += m_support->logic[current]->posBalance <= 20;
1095         comparison += ((m_support->logic[current]->diffAFD <= 0) && (m_support->logic[current]->diffTSC <= 0));
1096         comparison += (m_support->logic[current]->diffAFD <= m_support->logic[current]->diffTSC);
1097 
1098         if (comparison == 7)
1099             return Same;
1100     }
1101     else if ((m_dataIn->interlaceMode == ASCbotfieldFirst_frame) || (m_dataIn->interlaceMode == ASCtopfieldfirst_frame)) {
1102         comparison += m_support->logic[current]->AFD == m_support->logic[current]->TSC;
1103         comparison += m_support->logic[current]->AFD <= 9;
1104         comparison += m_support->logic[current]->gchDC <= 1;
1105         comparison += m_support->logic[current]->RsCsDiff <= 9;
1106         comparison += ((m_support->logic[current]->diffAFD <= 1) && (m_support->logic[current]->diffTSC <= 1));
1107         comparison += (m_support->logic[current]->diffAFD <= m_support->logic[current]->diffTSC);
1108 
1109         if (comparison == 6)
1110             return Same;
1111     }
1112     else {
1113         ASC_PRINTF("Error: Invalid interlace mode for stats comparison\n");
1114         assert(!"Error: Invalid interlace mode for stats comparison\n");
1115     }
1116 
1117     return Not_same;
1118 }
1119 
DenoiseIFrameRec()1120 bool ASC::DenoiseIFrameRec() {
1121     bool
1122         result = false;
1123     mfxF64
1124         c1 = 10.24346,
1125         c0 = -11.5751,
1126         x = (mfxF64)m_support->logic[ASCcurrent_frame_data]->SC,
1127         y = (mfxF64)m_support->logic[ASCcurrent_frame_data]->avgVal;
1128     result = ((c1 * std::log(x)) + c0) >= y;
1129     return result;
1130 }
1131 
FrameRepeatCheck()1132 bool ASC::FrameRepeatCheck() {
1133     mfxU8 reference = ASCprevious_frame_data;
1134     if (m_dataIn->interlaceMode > ASCprogressive_frame)
1135         reference = ASCprevious_previous_frame_data;
1136     return(CompareStats(ASCcurrent_frame_data, reference));
1137 }
1138 
DoMCTFFilteringCheck()1139 bool ASC::DoMCTFFilteringCheck() {
1140     return true;
1141 }
1142 
DetectShotChangeFrame()1143 void ASC::DetectShotChangeFrame() {
1144     m_support->logic[ASCcurrent_frame_data]->frameNum   = m_videoData[ASCCurrent_Frame]->frame_number;
1145     m_support->logic[ASCcurrent_frame_data]->firstFrame = m_support->firstFrame;
1146     m_support->logic[ASCcurrent_frame_data]->avgVal     = m_videoData[ASCCurrent_Frame]->layer.avgval;
1147     /*---------RsCs data--------*/
1148     m_support->logic[ASCcurrent_frame_data]->Rs = m_videoData[ASCCurrent_Frame]->layer.RsVal;
1149     m_support->logic[ASCcurrent_frame_data]->Cs = m_videoData[ASCCurrent_Frame]->layer.CsVal;
1150     m_support->logic[ASCcurrent_frame_data]->SC = m_videoData[ASCCurrent_Frame]->layer.RsVal + m_videoData[ASCCurrent_Frame]->layer.CsVal;
1151     m_support->logic[ASCcurrent_frame_data]->doFilter_flag    = DoMCTFFilteringCheck();
1152     m_support->logic[ASCcurrent_frame_data]->filterIntra_flag = DenoiseIFrameRec();
1153     if (m_support->firstFrame) {
1154         m_support->logic[ASCcurrent_frame_data]->TSC                = 0;
1155         m_support->logic[ASCcurrent_frame_data]->AFD                = 0;
1156         m_support->logic[ASCcurrent_frame_data]->TSCindex           = 0;
1157         m_support->logic[ASCcurrent_frame_data]->SCindex            = 0;
1158         m_support->logic[ASCcurrent_frame_data]->Schg               = 0;
1159         m_support->logic[ASCcurrent_frame_data]->Gchg               = 0;
1160         m_support->logic[ASCcurrent_frame_data]->picType            = 0;
1161         m_support->logic[ASCcurrent_frame_data]->lastFrameInShot    = 0;
1162         m_support->logic[ASCcurrent_frame_data]->pdist              = 0;
1163         m_support->logic[ASCcurrent_frame_data]->MVdiffVal          = 0;
1164         m_support->logic[ASCcurrent_frame_data]->RsCsDiff           = 0;
1165         m_support->logic[ASCcurrent_frame_data]->last_shot_distance = 0;
1166         m_support->logic[ASCcurrent_frame_data]->tcor               = 0;
1167         m_support->logic[ASCcurrent_frame_data]->mcTcor             = 0;
1168         m_support->firstFrame = false;
1169     }
1170     else {
1171         /*--------Motion data-------*/
1172         MotionAnalysis(m_videoData[ASCCurrent_Frame], m_videoData[ASCReference_Frame], &m_support->logic[ASCcurrent_frame_data]->TSC, &m_support->logic[ASCcurrent_frame_data]->AFD, &m_support->logic[ASCcurrent_frame_data]->MVdiffVal, &m_support->logic[ASCcurrent_frame_data]->AbsMVSize, &m_support->logic[ASCcurrent_frame_data]->AbsMVHSize, &m_support->logic[ASCcurrent_frame_data]->AbsMVVSize, (ASCLayers)0);
1173         m_support->logic[ASCcurrent_frame_data]->TSCindex = TableLookUp(NumTSC, lmt_tsc2, m_support->logic[ASCcurrent_frame_data]->TSC);
1174         m_support->logic[ASCcurrent_frame_data]->SCindex  = TableLookUp(NumSC, lmt_sc2, m_support->logic[ASCcurrent_frame_data]->SC);
1175         m_support->logic[ASCcurrent_frame_data]->pdist    = m_support->PDistanceTable[(m_support->logic[ASCcurrent_frame_data]->TSCindex * NumSC) +
1176                                                           m_support->logic[ASCcurrent_frame_data]->SCindex];
1177         m_support->logic[ASCcurrent_frame_data]->TSC >>= 5;
1178         m_support->logic[ASCcurrent_frame_data]->tcor = m_videoData[ASCCurrent_Frame]->layer.tcor;
1179         m_support->logic[ASCcurrent_frame_data]->mcTcor = m_videoData[ASCCurrent_Frame]->layer.mcTcor;
1180         /*------Shot Detection------*/
1181         m_support->logic[ASCcurrent_frame_data]->Schg = ShotDetect(m_videoData[ASCCurrent_Frame]->layer, m_videoData[ASCReference_Frame]->layer, *m_dataIn->layer, m_support->logic[ASCcurrent_frame_data], m_support->logic[ASCprevious_frame_data], m_support->control);
1182         m_support->logic[ASCprevious_frame_data]->lastFrameInShot = (mfxU8)m_support->logic[ASCcurrent_frame_data]->Schg;
1183         m_support->logic[ASCcurrent_frame_data]->repeatedFrame = FrameRepeatCheck();
1184     }
1185     m_dataIn->processed_frames++;
1186 }
1187 
1188 /**
1189 ***********************************************************************
1190 * \Brief Adds LTR friendly frame decision to list
1191 *
1192 * Adds frame number and ltr friendly frame decision pair to list, but
1193 * first checks if the size of the list is same or less to MAXLTRHISTORY,
1194 * if the list is longer, then it removes the top elements of the list
1195 * until it is MAXLTRHISTORY - 1, then it adds the new pair to the bottom
1196 * of the list.
1197 *
1198 * \return none
1199 */
Put_LTR_Hint()1200 void ASC::Put_LTR_Hint() {
1201     mfxI16
1202         list_size = (mfxI16)ltr_check_history.size();
1203     for (mfxI16 i = 0; i < list_size - (MAXLTRHISTORY - 1); i++)
1204         ltr_check_history.pop_front();
1205     ltr_check_history.push_back(std::make_pair(m_videoData[ASCCurrent_Frame]->frame_number, m_support->logic[ASCcurrent_frame_data]->ltr_flag));
1206 }
1207 
1208 /**
1209 ***********************************************************************
1210 * \Brief Checks LTR friendly decision history per frame and returns if
1211 *        LTR operation should be turn on or off.
1212 *
1213 * Travels the LTR friendly decision list backwards checking for frequency
1214 * and amount of true/false LTR friendly frame decision, based on the
1215 * good and bad limit inputs, if bad limit condition is reached first,
1216 * then it inmediately returns 0 (zero) which means to stop LTR operation
1217 *
1218 * \param goodLTRLimit      [IN] - Amount of true values to determine
1219 *                                 if the sequence should run in LTR mode.
1220 * \param badLTRLimit       [IN] - Amount of consecutive false values to
1221 *                                 stop LTR mode.
1222 *
1223 * \return ASC_LTR_DEC to flag stop(false)/continue(true) or FORCE LTR operation
1224 */
Continue_LTR_Mode(mfxU16 goodLTRLimit,mfxU16 badLTRLimit)1225 ASC_LTR_DEC ASC::Continue_LTR_Mode(mfxU16 goodLTRLimit, mfxU16 badLTRLimit) {
1226     size_t
1227         goodLTRCounter = 0,
1228         goodLTRRelativeCount = 0,
1229         badLTRCounter = 0,
1230         list_size = ltr_check_history.size();
1231     std::list<std::pair<mfxI32, bool> >::iterator
1232         ltr_list_it = std::prev(ltr_check_history.end());
1233     goodLTRLimit = goodLTRLimit > MAXLTRHISTORY ? MAXLTRHISTORY : goodLTRLimit;
1234     //When a scene change happens, all history is discarded
1235     if (Get_frame_shot_Decision()) {
1236         ltr_check_history.resize(0);
1237         list_size = 0;
1238     }
1239     //If not enough history then let it be LTR
1240     if (list_size < badLTRLimit)
1241         return YES_LTR;
1242     //Travel trhough the list to determine if LTR operation should be kept on
1243     mfxU16
1244         bkp_size = (mfxU16)list_size;
1245     while ((bkp_size > 1) && (goodLTRCounter < goodLTRLimit)) {
1246         auto scd = ltr_list_it->second;
1247         if (!scd) {
1248             badLTRCounter++;
1249             goodLTRRelativeCount = 0;
1250         }
1251         if (badLTRCounter >= badLTRLimit)
1252             return NO_LTR;
1253         goodLTRCounter += (mfxU16)ltr_list_it->second;
1254         goodLTRRelativeCount += (mfxU16)ltr_list_it->second;
1255         if (goodLTRRelativeCount >= badLTRLimit)
1256             badLTRCounter = 0;
1257         ltr_list_it = std::prev(ltr_list_it);
1258         bkp_size--;
1259     }
1260     if (goodLTRCounter >= goodLTRLimit)
1261         return FORCE_LTR;
1262     else if (goodLTRRelativeCount >= (size_t)NMIN(badLTRLimit, list_size - 1) && badLTRCounter < goodLTRRelativeCount)
1263         return YES_LTR;
1264     else
1265         return NO_LTR;
1266 }
1267 
SetKernel(SurfaceIndex * idxFrom,SurfaceIndex * idxTo,CmTask ** subSamplingTask,mfxU32 parity)1268 mfxStatus ASC::SetKernel(SurfaceIndex *idxFrom, SurfaceIndex *idxTo, CmTask **subSamplingTask, mfxU32 parity) {
1269     mfxU32 argIdx = 0;
1270     INT res;
1271     //Progressive Point subsampling kernel
1272 
1273     CmKernel
1274         **subKernel = nullptr;
1275 
1276     if (m_dataIn->interlaceMode == ASCprogressive_frame) {
1277         subKernel = &m_kernel_p;
1278     }
1279     else {
1280         if (parity == ASCTopField)
1281             subKernel = &m_kernel_t;
1282         else if (parity == ASCBottomField)
1283             subKernel = &m_kernel_b;
1284         else
1285             return MFX_ERR_UNDEFINED_BEHAVIOR;
1286     }
1287 
1288     int
1289         tmp_subWidth = subWidth,
1290         tmp_subHeight = subHeight;
1291 
1292     res = (*subKernel)->SetKernelArg(argIdx++, sizeof(SurfaceIndex), idxFrom);
1293     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1294     res = (*subKernel)->SetKernelArg(argIdx++, sizeof(SurfaceIndex), idxTo);
1295     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1296     res = (*subKernel)->SetKernelArg(argIdx++, sizeof(int), &m_gpuwidth);
1297     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1298     res = (*subKernel)->SetKernelArg(argIdx++, sizeof(int), &m_gpuheight);
1299     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1300     res = (*subKernel)->SetKernelArg(argIdx++, sizeof(int), &tmp_subWidth);
1301     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1302     res = (*subKernel)->SetKernelArg(argIdx++, sizeof(int), &tmp_subHeight);
1303     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1304     /*if (*subSamplingTask)
1305     res = (*subSamplingTask)->Reset();
1306     else
1307     */res = m_device->CreateTask(*subSamplingTask);
1308     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1309     res = (*subSamplingTask)->AddKernel((*subKernel));
1310     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1311 
1312     return MFX_ERR_NONE;
1313 }
1314 
SetKernel(SurfaceIndex * idxFrom,CmTask ** subSamplingTask,mfxU32 parity)1315 mfxStatus ASC::SetKernel(SurfaceIndex *idxFrom, CmTask **subSamplingTask, mfxU32 parity) {
1316     return (SetKernel(idxFrom, m_videoData[ASCCurrent_Frame]->layer.idxImage, subSamplingTask, parity));
1317 }
1318 
SetKernel(SurfaceIndex * idxFrom,mfxU32 parity)1319 mfxStatus ASC::SetKernel(SurfaceIndex *idxFrom, mfxU32 parity) {
1320     return(SetKernel(idxFrom, &m_task, parity));
1321 }
1322 
1323 #ifndef CMRT_EMU
QueueFrame(SurfaceIndex * idxFrom,SurfaceIndex * idxTo,CmEvent ** subSamplingEv,CmTask ** subSamplingTask,mfxU32 parity)1324 mfxStatus ASC::QueueFrame(SurfaceIndex *idxFrom, SurfaceIndex *idxTo, CmEvent **subSamplingEv, CmTask **subSamplingTask, mfxU32 parity)
1325 #else
1326 mfxStatus ASC::QueueFrame(SurfaceIndex *idxFrom, SurfaceIndex *idxTo, CmEvent **subSamplingEv, CmTask **subSamplingTask, CmThreadSpace *subThreadSpace, mfxU32 parity)
1327 #endif
1328 {
1329 if (!m_ASCinitialized)
1330 return MFX_ERR_NOT_INITIALIZED;
1331 *subSamplingEv = NULL;// CM_NO_EVENT;
1332 INT res;
1333 res = SetKernel(idxFrom, idxTo, subSamplingTask, parity);
1334 SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1335 #ifndef CMRT_EMU
1336 res = m_queue->Enqueue(*subSamplingTask, *subSamplingEv);
1337 #else
1338 res = m_queue->Enqueue(*subSamplingTask, *subSamplingEv, subThreadSpace);
1339 #endif
1340 SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1341 return MFX_ERR_NONE;
1342 }
1343 
1344 #ifndef CMRT_EMU
QueueFrame(SurfaceIndex * idxFrom,CmEvent ** subSamplingEv,CmTask ** subSamplingTask,mfxU32 parity)1345 mfxStatus ASC::QueueFrame(SurfaceIndex *idxFrom, CmEvent **subSamplingEv, CmTask **subSamplingTask, mfxU32 parity)
1346 #else
1347 mfxStatus ASC::QueueFrame(SurfaceIndex *idxFrom, CmEvent **subSamplingEv, CmTask **subSamplingTask, CmThreadSpace *subThreadSpace, mfxU32 parity)
1348 #endif
1349 {
1350 #ifndef CMRT_EMU
1351     return(QueueFrame(idxFrom, m_videoData[ASCCurrent_Frame]->layer.idxImage, subSamplingEv, subSamplingTask, parity));
1352 #else
1353     return(QueueFrame(idxFrom, m_videoData[ASCCurrent_Frame]->layer.idxImage, subSamplingEv, subSamplingTask, subThreadSpace, parity));
1354 #endif
1355 }
1356 
QueueFrame(SurfaceIndex * idxFrom,mfxU32 parity)1357 mfxStatus ASC::QueueFrame(SurfaceIndex *idxFrom, mfxU32 parity) {
1358     return(
1359 #ifndef CMRT_EMU
1360         QueueFrame(idxFrom, &m_subSamplingEv, &m_task, parity)
1361 #else
1362         QueueFrame(idxFrom, &m_subSamplingEv, &m_task, m_threadSpace, parity)
1363 #endif
1364         );
1365 }
1366 
AscFrameAnalysis()1367 void ASC::AscFrameAnalysis() {
1368     mfxU8
1369         *ss = m_videoData[ASCCurrent_Frame]->layer.Image.Y;
1370 
1371     mfxU32
1372         sumAll = 0;
1373     for (mfxU16 i = 0; i < m_dataIn->layer->_cheight; i++) {
1374         for (mfxU16 j = 0; j < m_dataIn->layer->_cwidth; j++)
1375             sumAll += ss[j];
1376         ss += m_dataIn->layer->Extended_Width;
1377     }
1378     sumAll >>= 13;
1379     m_videoData[ASCCurrent_Frame]->layer.avgval = (mfxU16)sumAll;
1380     RsCsCalc();
1381     DetectShotChangeFrame();
1382     Put_LTR_Hint();
1383     GeneralBufferRotation();
1384 }
1385 
Query_resize_Event()1386 ASC_API bool ASC::Query_resize_Event() {
1387     return (m_subSamplingEv != nullptr);
1388 }
1389 
ProcessQueuedFrame(CmEvent ** subSamplingEv,CmTask ** subSamplingTask,CmSurface2DUP ** inputFrame,mfxU8 ** pixelData)1390 ASC_API mfxStatus ASC::ProcessQueuedFrame(CmEvent **subSamplingEv, CmTask **subSamplingTask, CmSurface2DUP **inputFrame, mfxU8 **pixelData)
1391 {
1392     if (!m_ASCinitialized)
1393         return MFX_ERR_NOT_INITIALIZED;
1394     INT res;
1395     if (*subSamplingEv) {
1396         res = (*subSamplingEv)->WaitForTaskFinished();
1397         if (res == CM_EXCEED_MAX_TIMEOUT)
1398             return MFX_ERR_GPU_HANG;
1399         SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1400         if(inputFrame != nullptr && pixelData != nullptr)
1401             MFX_SAFE_CALL(SwapResources(ASCCurrent_Frame, inputFrame, pixelData))
1402         AscFrameAnalysis();
1403         res = m_queue->DestroyEvent(*subSamplingEv);
1404         SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1405         res = m_device->DestroyTask(*subSamplingTask);
1406         SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1407         m_dataReady = (res == CM_SUCCESS);
1408     }
1409     else {
1410         return MFX_ERR_DEVICE_FAILED;
1411     }
1412     return MFX_ERR_NONE;
1413 }
1414 
ProcessQueuedFrame()1415 ASC_API mfxStatus ASC::ProcessQueuedFrame()
1416 {
1417     return ProcessQueuedFrame(&m_subSamplingEv, &m_task, nullptr, nullptr);
1418 }
1419 
RunFrame(SurfaceIndex * idxFrom,mfxU32 parity)1420 mfxStatus ASC::RunFrame(SurfaceIndex *idxFrom, mfxU32 parity) {
1421     if (!m_ASCinitialized)
1422         return MFX_ERR_NOT_INITIALIZED;
1423     CmEvent* e = NULL;// CM_NO_EVENT;
1424     INT res;
1425     res = SetKernel(idxFrom, parity);
1426     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1427 #ifndef CMRT_EMU
1428     res = m_queue->Enqueue(m_task, e);
1429 #else
1430     res = m_queue->Enqueue(m_task, e, m_threadSpace);
1431 #endif
1432     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1433     res = e->WaitForTaskFinished();
1434     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1435     res = m_device->DestroyTask(m_task);
1436     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1437     res = m_queue->DestroyEvent(e);
1438     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1439 
1440     AscFrameAnalysis();
1441 
1442     return MFX_ERR_NONE;
1443 }
1444 
QueueFrame(mfxHDL frameHDL,SurfaceIndex * idxTo,CmEvent ** subSamplingEv,CmTask ** subSamplingTask,mfxU32 parity)1445 mfxStatus ASC::QueueFrame(mfxHDL frameHDL, SurfaceIndex *idxTo, CmEvent **subSamplingEv, CmTask **subSamplingTask, mfxU32 parity)
1446 {
1447     if (!m_ASCinitialized)
1448         return MFX_ERR_NOT_INITIALIZED;
1449     m_videoData[ASCCurrent_Frame]->frame_number = m_videoData[ASCReference_Frame]->frame_number + 1;
1450 
1451     CmSurface2D* p_surfaceFrom = nullptr;
1452     SurfaceIndex* idxFrom = nullptr;
1453 
1454     CreateCmSurface2D(reinterpret_cast<AbstractSurfaceHandle>(frameHDL), p_surfaceFrom, idxFrom);
1455 
1456     mfxStatus sts = QueueFrame(idxFrom, idxTo, subSamplingEv, subSamplingTask, parity);
1457     SCD_CHECK_MFX_ERR(sts);
1458 
1459     return MFX_ERR_NONE;
1460 }
1461 
1462 
QueueFrame(mfxHDL frameHDL,CmEvent ** subSamplingEv,CmTask ** subSamplingTask,mfxU32 parity)1463 mfxStatus ASC::QueueFrame(mfxHDL frameHDL, CmEvent **subSamplingEv, CmTask **subSamplingTask, mfxU32 parity)
1464 {
1465     if (!m_ASCinitialized)
1466         return MFX_ERR_NOT_INITIALIZED;
1467     m_videoData[ASCCurrent_Frame]->frame_number = m_videoData[ASCReference_Frame]->frame_number + 1;
1468 
1469     CmSurface2D* p_surfaceFrom = nullptr;
1470     SurfaceIndex* idxFrom = nullptr;
1471 
1472     CreateCmSurface2D(reinterpret_cast<AbstractSurfaceHandle>(frameHDL), p_surfaceFrom, idxFrom);
1473 
1474     mfxStatus sts = QueueFrame(idxFrom, subSamplingEv, subSamplingTask, parity);
1475     SCD_CHECK_MFX_ERR(sts);
1476 
1477     return MFX_ERR_NONE;
1478 }
1479 
QueueFrame(mfxHDL frameHDL,mfxU32 parity)1480 mfxStatus ASC::QueueFrame(mfxHDL frameHDL, mfxU32 parity) {
1481     if (!m_ASCinitialized)
1482         return MFX_ERR_NOT_INITIALIZED;
1483     m_videoData[ASCCurrent_Frame]->frame_number = m_videoData[ASCReference_Frame]->frame_number + 1;
1484 
1485     CmSurface2D* p_surfaceFrom = nullptr;
1486     SurfaceIndex* idxFrom = nullptr;
1487 
1488     CreateCmSurface2D(reinterpret_cast<AbstractSurfaceHandle>(frameHDL), p_surfaceFrom, idxFrom);
1489 
1490     mfxStatus sts = QueueFrame(idxFrom, parity);
1491     SCD_CHECK_MFX_ERR(sts);
1492 
1493     return MFX_ERR_NONE;
1494 }
1495 
RunFrame(mfxHDL frameHDL,mfxU32 parity)1496 mfxStatus ASC::RunFrame(mfxHDL frameHDL, mfxU32 parity) {
1497     if (!m_ASCinitialized)
1498         return MFX_ERR_NOT_INITIALIZED;
1499     m_videoData[ASCCurrent_Frame]->frame_number = m_videoData[ASCReference_Frame]->frame_number + 1;
1500 
1501     CmSurface2D* p_surfaceFrom = 0;
1502 
1503     SurfaceIndex *idxFrom = nullptr;
1504     CreateCmSurface2D(reinterpret_cast<AbstractSurfaceHandle>(frameHDL), p_surfaceFrom, idxFrom);
1505 
1506     mfxStatus sts = RunFrame(idxFrom, parity);
1507     SCD_CHECK_MFX_ERR(sts);
1508 
1509     return MFX_ERR_NONE;
1510 }
1511 
RunFrame(mfxU8 * frame,mfxU32 parity)1512 mfxStatus ASC::RunFrame(mfxU8 *frame, mfxU32 parity) {
1513     if (!m_ASCinitialized)
1514         return MFX_ERR_NOT_INITIALIZED;
1515     m_videoData[ASCCurrent_Frame]->frame_number = m_videoData[ASCReference_Frame]->frame_number + 1;
1516     (this->*(resizeFunc))(frame, m_width, m_height, m_pitch, (ASCLayers)0, parity);
1517     RsCsCalc();
1518     DetectShotChangeFrame();
1519     Put_LTR_Hint();
1520     GeneralBufferRotation();
1521     return MFX_ERR_NONE;
1522 }
1523 
QueueFrameProgressive(SurfaceIndex * idxSurf)1524 ASC_API mfxStatus ASC::QueueFrameProgressive(SurfaceIndex* idxSurf) {
1525     mfxStatus sts = QueueFrame(idxSurf, ASCTopField);
1526     return sts;
1527 }
1528 
QueueFrameProgressive(SurfaceIndex * idxSurf,CmEvent * subSamplingEv,CmTask * subSamplingTask)1529 ASC_API mfxStatus ASC::QueueFrameProgressive(SurfaceIndex* idxSurf, CmEvent *subSamplingEv, CmTask *subSamplingTask) {
1530     mfxStatus sts = QueueFrame(idxSurf, &subSamplingEv, &subSamplingTask, ASCTopField);
1531     return sts;
1532 }
1533 
QueueFrameProgressive(mfxHDL surface,SurfaceIndex * idxTo,CmEvent ** subSamplingEv,CmTask ** subSamplingTask)1534 ASC_API mfxStatus ASC::QueueFrameProgressive(mfxHDL surface, SurfaceIndex *idxTo, CmEvent **subSamplingEv, CmTask **subSamplingTask)
1535 {
1536     mfxStatus sts = QueueFrame(surface, idxTo, subSamplingEv, subSamplingTask, ASCTopField);
1537     return sts;
1538 }
1539 
QueueFrameProgressive(mfxHDL surface,CmEvent ** subSamplingEv,CmTask ** subSamplingTask)1540 ASC_API mfxStatus ASC::QueueFrameProgressive(mfxHDL surface, CmEvent **subSamplingEv, CmTask **subSamplingTask) {
1541     mfxStatus sts = QueueFrame(surface, subSamplingEv, subSamplingTask, ASCTopField);
1542     return sts;
1543 }
1544 
QueueFrameProgressive(mfxHDL surface)1545 ASC_API mfxStatus ASC::QueueFrameProgressive(mfxHDL surface) {
1546     mfxStatus sts = QueueFrame(surface, ASCTopField);
1547     return sts;
1548 }
1549 
PutFrameProgressive(SurfaceIndex * idxSurf)1550 ASC_API mfxStatus ASC::PutFrameProgressive(SurfaceIndex* idxSurf) {
1551     mfxStatus sts = RunFrame(idxSurf, ASCTopField);
1552     m_dataReady = (sts == MFX_ERR_NONE);
1553     return sts;
1554 }
1555 
PutFrameProgressive(mfxHDL surface)1556 ASC_API mfxStatus ASC::PutFrameProgressive(mfxHDL surface) {
1557     mfxStatus sts = RunFrame(surface, ASCTopField);
1558     m_dataReady = (sts == MFX_ERR_NONE);
1559     return sts;
1560 }
1561 
PutFrameProgressive(mfxU8 * frame,mfxI32 Pitch)1562 ASC_API mfxStatus ASC::PutFrameProgressive(mfxU8 *frame, mfxI32 Pitch) {
1563     mfxStatus sts;
1564     if (Pitch > 0) {
1565         sts = SetPitch(Pitch);
1566         SCD_CHECK_MFX_ERR(sts);
1567     }
1568 
1569     sts = RunFrame(frame, ASCTopField);
1570     SCD_CHECK_MFX_ERR(sts);
1571     m_dataReady = (sts == MFX_ERR_NONE);
1572     return sts;
1573 }
1574 
PutFrameInterlaced(mfxU8 * frame,mfxI32 Pitch)1575 ASC_API mfxStatus ASC::PutFrameInterlaced(mfxU8 *frame, mfxI32 Pitch) {
1576     mfxStatus sts;
1577 
1578     if (Pitch > 0) {
1579         sts = SetPitch(Pitch);
1580         SCD_CHECK_MFX_ERR(sts);
1581     }
1582 
1583     sts = RunFrame(frame, m_dataIn->currentField);
1584     m_dataReady = (sts == MFX_ERR_NONE);
1585     SetNextField();
1586     return sts;
1587 }
1588 
QueueFrameInterlaced(SurfaceIndex * idxSurf)1589 ASC_API mfxStatus ASC::QueueFrameInterlaced(SurfaceIndex* idxSurf) {
1590     mfxStatus sts = QueueFrame(idxSurf, m_dataIn->currentField);
1591     m_dataReady = (sts == MFX_ERR_NONE);
1592     SetNextField();
1593     return sts;
1594 }
1595 
PutFrameInterlaced(SurfaceIndex * idxSurf)1596 ASC_API mfxStatus ASC::PutFrameInterlaced(SurfaceIndex* idxSurf) {
1597     mfxStatus sts = RunFrame(idxSurf, m_dataIn->currentField);
1598     m_dataReady = (sts == MFX_ERR_NONE);
1599     SetNextField();
1600     return sts;
1601 }
1602 
QueueFrameInterlaced(mfxHDL surface)1603 ASC_API mfxStatus ASC::QueueFrameInterlaced(mfxHDL surface) {
1604     mfxStatus sts = QueueFrame(surface, m_dataIn->currentField);
1605     SetNextField();
1606     return sts;
1607 }
1608 
PutFrameInterlaced(mfxHDL surface)1609 ASC_API mfxStatus ASC::PutFrameInterlaced(mfxHDL surface) {
1610     mfxStatus sts = RunFrame(surface, m_dataIn->currentField);
1611     m_dataReady = (sts == MFX_ERR_NONE);
1612     SetNextField();
1613     return sts;
1614 }
1615 
1616 
calc_RaCa_pic(mfxU8 * pSrc,mfxI32 width,mfxI32 height,mfxI32 pitch,mfxF64 & RsCs)1617 ASC_API mfxStatus ASC::calc_RaCa_pic(mfxU8 *pSrc, mfxI32 width, mfxI32 height, mfxI32 pitch, mfxF64 &RsCs) {
1618     if (!m_ASCinitialized)
1619         return MFX_ERR_NOT_INITIALIZED;
1620     return Calc_RaCa_pic(pSrc, width, height, pitch, RsCs);
1621 }
1622 
calc_RaCa_Surf(mfxHDL surface,mfxF64 & rscs)1623 ASC_API mfxStatus ASC::calc_RaCa_Surf(mfxHDL surface, mfxF64 &rscs) {
1624     if (!Query_ASCCmDevice())
1625         return MFX_ERR_UNDEFINED_BEHAVIOR;
1626 
1627     mfxStatus sts = CopyFrameSurface(surface);
1628     SCD_CHECK_MFX_ERR(sts);
1629 
1630     sts = calc_RaCa_pic(m_frameBkp, m_gpuwidth, m_gpuheight, m_gpuImPitch, rscs);
1631     SCD_CHECK_MFX_ERR(sts);
1632 
1633     return sts;
1634 }
1635 
CreateCmSurface2D(void * pSrcD3D,CmSurface2D * & pCmSurface2D,SurfaceIndex * & pCmSrcIndex)1636 mfxStatus ASC::CreateCmSurface2D(void *pSrcD3D, CmSurface2D* & pCmSurface2D, SurfaceIndex* &pCmSrcIndex)
1637 {
1638     INT cmSts = 0;
1639     std::map<void *, CmSurface2D *>::iterator it;
1640     std::map<CmSurface2D *, SurfaceIndex *>::iterator it_idx;
1641     it = m_tableCmRelations2.find(pSrcD3D);
1642     if (m_tableCmRelations2.end() == it)
1643     {
1644         //UMC::AutomaticUMCMutex guard(m_guard);
1645         {
1646             cmSts = m_device->CreateSurface2D((AbstractSurfaceHandle *)pSrcD3D, pCmSurface2D);
1647             SCD_CHECK_CM_ERR(cmSts, MFX_ERR_DEVICE_FAILED);
1648             m_tableCmRelations2.insert(std::pair<void *, CmSurface2D *>(pSrcD3D, pCmSurface2D));
1649         }
1650 
1651         cmSts = pCmSurface2D->GetIndex(pCmSrcIndex);
1652         SCD_CHECK_CM_ERR(cmSts, MFX_ERR_DEVICE_FAILED);
1653         m_tableCmIndex2.insert(std::pair<CmSurface2D *, SurfaceIndex *>(pCmSurface2D, pCmSrcIndex));
1654     }
1655     else
1656     {
1657         pCmSurface2D = it->second;
1658         it_idx = m_tableCmIndex2.find(pCmSurface2D);
1659         if (it_idx == m_tableCmIndex2.end())
1660             return MFX_ERR_UNDEFINED_BEHAVIOR;
1661         else
1662             pCmSrcIndex = it_idx->second;
1663     }
1664 
1665     return MFX_ERR_NONE;
1666 }
1667 
CopyFrameSurface(mfxHDL frameHDL)1668 mfxStatus ASC::CopyFrameSurface(mfxHDL frameHDL) {
1669     if (!m_ASCinitialized)
1670         return MFX_ERR_NOT_INITIALIZED;
1671     CmSurface2D* p_surfaceFrom = 0;
1672     mfxStatus sts;
1673     INT res;
1674     SurfaceIndex *idxFrom;
1675 
1676     sts = CreateCmSurface2D(reinterpret_cast<AbstractSurfaceHandle>(frameHDL), p_surfaceFrom, idxFrom);
1677     SCD_CHECK_MFX_ERR(sts);
1678 
1679     m_frameCopyEv = NULL;// CM_NO_EVENT;
1680     mfxU32 argIdx = 0;
1681     //Copy pixels kernel
1682     res = m_kernel_cp->SetKernelArg(argIdx++, sizeof(SurfaceIndex), idxFrom);
1683     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1684     res = m_kernel_cp->SetKernelArg(argIdx++, sizeof(SurfaceIndex), m_pIdxSurfCp);
1685     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1686 
1687     mfxU32
1688         width_dword = (UINT)ceil((double)m_gpuwidth / 4);
1689     res = m_kernel_cp->SetKernelArg(argIdx++, sizeof(mfxU32), &width_dword);
1690     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1691     res = m_kernel_cp->SetKernelArg(argIdx++, sizeof(mfxI32), &m_gpuheight);
1692     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1693     res = m_kernel_cp->SetKernelArg(argIdx++, sizeof(mfxU32), &m_gpuImPitch);
1694     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1695 
1696     res = m_device->CreateTask(m_taskCp);
1697     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1698     res = m_taskCp->AddKernel(m_kernel_cp);      //progressive
1699     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1700 #ifndef CMRT_EMU
1701     res = m_queue->Enqueue(m_taskCp, m_frameCopyEv);
1702 #else
1703     res = m_queue->Enqueue(m_taskCp, m_frameCopyEv, m_threadSpaceCp);
1704 #endif
1705     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1706     res = m_frameCopyEv->WaitForTaskFinished();
1707     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1708     res = m_device->DestroyTask(m_taskCp);
1709     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1710     res = m_queue->DestroyEvent(m_frameCopyEv);
1711     SCD_CHECK_CM_ERR(res, MFX_ERR_DEVICE_FAILED);
1712     return sts;
1713 }
1714 
Get_Last_frame_Data()1715 ASC_API bool ASC::Get_Last_frame_Data() {
1716     if(m_dataReady)
1717         GeneralBufferRotation();
1718     else
1719         ASC_PRINTF("Warning: Trying to grab data not ready\n");
1720     return(m_dataReady);
1721 }
1722 
Get_asc_subsampling_width()1723 ASC_API mfxU16 ASC::Get_asc_subsampling_width()
1724 {
1725     return mfxU16(subWidth);
1726 }
1727 
Get_asc_subsampling_height()1728 ASC_API mfxU16 ASC::Get_asc_subsampling_height()
1729 {
1730     return mfxU16(subHeight);
1731 }
1732 
Get_starting_frame_number()1733 ASC_API mfxU32 ASC::Get_starting_frame_number() {
1734     return m_dataIn->starting_frame;
1735 }
1736 
Get_frame_number()1737 ASC_API mfxU32 ASC::Get_frame_number() {
1738     if(m_dataReady)
1739         return m_support->logic[ASCprevious_frame_data]->frameNum;
1740     else
1741         return 0;
1742 }
1743 
Get_frame_shot_Decision()1744 ASC_API mfxU32 ASC::Get_frame_shot_Decision() {
1745     if(m_dataReady)
1746         return m_support->logic[ASCprevious_frame_data]->Schg;
1747     else
1748         return 0;
1749 }
1750 
Get_frame_last_in_scene()1751 ASC_API mfxU32 ASC::Get_frame_last_in_scene() {
1752     if(m_dataReady)
1753         return m_support->logic[ASCprevious_frame_data]->lastFrameInShot;
1754     else
1755         return 0;
1756 }
1757 
Get_GoPcorrected_frame_shot_Decision()1758 ASC_API bool ASC::Get_GoPcorrected_frame_shot_Decision() {
1759     if(m_dataReady)
1760         return (m_support->detectedSch > 0);
1761     else
1762         return 0;
1763 }
Get_frame_Spatial_complexity()1764 ASC_API mfxI32 ASC::Get_frame_Spatial_complexity() {
1765     if(m_dataReady)
1766         return m_support->logic[ASCprevious_frame_data]->SCindex;
1767     else
1768         return 0;
1769 }
1770 
Get_frame_Temporal_complexity()1771 ASC_API mfxI32 ASC::Get_frame_Temporal_complexity() {
1772     if(m_dataReady)
1773         return m_support->logic[ASCprevious_frame_data]->TSCindex;
1774     else
1775         return 0;
1776 }
1777 
Get_intra_frame_denoise_recommendation()1778 ASC_API bool ASC::Get_intra_frame_denoise_recommendation() {
1779     return m_support->logic[ASCprevious_frame_data]->filterIntra_flag;
1780 }
1781 
Get_PDist_advice()1782 ASC_API mfxU32 ASC::Get_PDist_advice() {
1783     if (m_dataReady)
1784         return m_support->logic[ASCprevious_frame_data]->pdist;
1785     else
1786         return NULL;
1787 }
1788 
Get_LTR_advice()1789 ASC_API bool ASC::Get_LTR_advice() {
1790     if (m_dataReady)
1791         return m_support->logic[ASCprevious_frame_data]->ltr_flag;
1792     else
1793         return NULL;
1794 }
1795 
Get_RepeatedFrame_advice()1796 ASC_API bool ASC::Get_RepeatedFrame_advice() {
1797     if (m_dataReady)
1798         return m_support->logic[ASCprevious_frame_data]->repeatedFrame;
1799     else
1800         return NULL;
1801 }
Get_Filter_advice()1802 ASC_API bool ASC::Get_Filter_advice() {
1803     return m_support->logic[ASCprevious_frame_data]->doFilter_flag;
1804 }
1805 
1806 /**
1807 ***********************************************************************
1808 * \Brief Tells if LTR mode should be on/off or forced on.
1809 *
1810 * \return  ASC_LTR_DEC& to flag stop(false)/continue(true) or force (2)
1811 *          LTR operation
1812 */
get_LTR_op_hint(ASC_LTR_DEC & scd_LTR_hint)1813 ASC_API mfxStatus ASC::get_LTR_op_hint(ASC_LTR_DEC& scd_LTR_hint) {
1814     if (!m_ASCinitialized)
1815         return MFX_ERR_NOT_INITIALIZED;
1816     scd_LTR_hint = Continue_LTR_Mode(50, 5);
1817     return MFX_ERR_NONE;
1818 }
1819 
Check_last_frame_processed(mfxU32 frameOrder)1820 ASC_API bool ASC::Check_last_frame_processed(mfxU32 frameOrder) {
1821     if (m_support->frameOrder <= frameOrder && (m_support->frameOrder == frameOrder && frameOrder > 0))
1822         return 0;
1823     else
1824         m_support->frameOrder = frameOrder;
1825     return 1;
1826 }
1827 
Reset_last_frame_processed()1828 ASC_API void ASC::Reset_last_frame_processed() {
1829     m_support->frameOrder = 0;
1830 }
1831 
Get_CpuFeature_AVX2()1832 ASC_API mfxI32 ASC::Get_CpuFeature_AVX2() {
1833     return CpuFeature_AVX2();
1834 }
Get_CpuFeature_SSE41()1835 ASC_API mfxI32 ASC::Get_CpuFeature_SSE41() {
1836     return CpuFeature_SSE41();
1837 }
1838 
bufferRotation(void * Buffer1,void * Buffer2)1839 void bufferRotation(void *Buffer1, void *Buffer2) {
1840     void
1841         *transfer;
1842     transfer = Buffer2;
1843     Buffer2  = Buffer1;
1844     Buffer1  = transfer;
1845 }
1846 
GeneralBufferRotation()1847 void ASC::GeneralBufferRotation() {
1848     ASCVidSample
1849         *videoTransfer;
1850     ASCTSCstat
1851         *metaTransfer;
1852 
1853     if (m_support->logic[ASCcurrent_frame_data]->repeatedFrame) {
1854         m_videoData[ASCReference_Frame]->frame_number = m_videoData[ASCCurrent_Frame]->frame_number;
1855         m_support->logic[ASCprevious_frame_data]->frameNum = m_support->logic[ASCcurrent_frame_data]->frameNum;
1856         m_support->logic[ASCcurrent_frame_data]->Schg = 0;
1857         m_support->logic[ASCprevious_frame_data]->Schg = 0;
1858         m_support->logic[ASCprevious_frame_data]->repeatedFrame = true;
1859         m_support->logic[ASCprevious_previous_frame_data]->Schg = 0;
1860     }
1861     else {
1862         videoTransfer = m_videoData[0];
1863         m_videoData[0] = m_videoData[1];
1864         m_videoData[1] = videoTransfer;
1865 
1866         metaTransfer = m_support->logic[ASCprevious_previous_frame_data];
1867         m_support->logic[ASCprevious_previous_frame_data] = m_support->logic[ASCprevious_frame_data];
1868         m_support->logic[ASCprevious_frame_data] = m_support->logic[ASCcurrent_frame_data];
1869         m_support->logic[ASCcurrent_frame_data] = metaTransfer;
1870     }
1871 }
1872 }