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, ¤t->RsDiff, ¤t->CsDiff);
959 ImageDiffHistogram(ssFrame, refFrame, imageInfo.Extended_Width, imageInfo._cwidth, imageInfo._cheight, current->histogram, ¤t->ssDCint, ¤t->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 }