• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3  * Copyright (c) Imagination Technologies Limited, UK
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Edward Lin <edward.lin@intel.com>
27  *
28  */
29 
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <memory.h>
33 #include "psb_drv_video.h"
34 #include "psb_drv_debug.h"
35 #include "tng_hostdefs.h"
36 #include "tng_hostcode.h"
37 #include "tng_hostair.h"
38 
39 /***********************************************************************************
40  * Function Name     : functions of pi8AIR_Table table
41  ************************************************************************************/
tng_air_buf_create(context_ENC_p ctx)42 VAStatus tng_air_buf_create(context_ENC_p ctx)
43 {
44     IMG_UINT32 ui32MbNum = (ctx->ui16PictureHeight * ctx->ui16Width) >> 8;
45     ctx->sAirInfo.pi8AIR_Table = (IMG_INT8 *)malloc(ui32MbNum);
46     drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: ui32MbNum = %d\n", __FUNCTION__, ui32MbNum);
47     if (!ctx->sAirInfo.pi8AIR_Table) {
48         drv_debug_msg(VIDEO_DEBUG_ERROR,
49             "\nERROR: Error allocating Adaptive Intra Refresh table of Application context (APP_SetVideoParams)");
50         return VA_STATUS_ERROR_ALLOCATION_FAILED;
51     }
52     memset(ctx->sAirInfo.pi8AIR_Table, 0, ui32MbNum);
53     return VA_STATUS_SUCCESS;
54 }
55 
tng_air_buf_clear(context_ENC_p ctx)56 static void tng_air_buf_clear(context_ENC_p ctx)
57 {
58 #if 0
59     IMG_UINT32 ui32MbNum = (ctx->ui16PictureHeight * ctx->ui16Width) >> 8;
60     drv_debug_msg(VIDEO_DEBUG_ERROR,"%s: ui32MbNum = %d, ctx->sAirInfo.pi8AIR_Table = 0x%08x\n", __FUNCTION__, ui32MbNum, ctx->sAirInfo.pi8AIR_Table);
61     memset(ctx->sAirInfo.pi8AIR_Table, 0, ui32MbNum);
62     drv_debug_msg(VIDEO_DEBUG_ERROR,"%s: ui32MbNum = %d, ctx->sAirInfo.pi8AIR_Table = 0x%08x\n", __FUNCTION__, ui32MbNum, ctx->sAirInfo.pi8AIR_Table);
63 #endif
64     tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID,
65         MTX_CMDID_SW_AIR_BUF_CLEAR, 0, 0, 0);
66     return ;
67 }
68 
tng_air_buf_free(context_ENC_p ctx)69 void tng_air_buf_free(context_ENC_p ctx)
70 {
71     if (ctx->sAirInfo.pi8AIR_Table != NULL)
72         free(ctx->sAirInfo.pi8AIR_Table);
73     return ;
74 }
75 
76 /***********************************************************************************
77  * Function Name     : functions for input control
78  ************************************************************************************/
tng__rand(context_ENC_p ctx)79 static IMG_UINT16 tng__rand(context_ENC_p ctx)
80 {
81     IMG_UINT16 ui16ret = 0;
82     ctx->ui32pseudo_rand_seed =  (IMG_UINT32) ((ctx->ui32pseudo_rand_seed * 1103515245 + 12345) & 0xffffffff); //Using mask, just in case
83     ui16ret = (IMG_UINT16)(ctx->ui32pseudo_rand_seed / 65536) % 32768;
84     return ui16ret;
85 }
86 
87 //APP_FillSliceMap
tng_fill_slice_map(context_ENC_p ctx,IMG_INT32 i32SlotNum,IMG_UINT32 ui32StreamIndex)88 IMG_UINT32 tng_fill_slice_map(context_ENC_p ctx, IMG_INT32 i32SlotNum, IMG_UINT32 ui32StreamIndex)
89 {
90     context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]);
91     unsigned char *pvBuffer;
92     IMG_UINT8 ui8SlicesPerPicture;
93     IMG_UINT8 ui8HalfWaySlice;
94     IMG_UINT32 ui32HalfwayBU;
95 
96     ui8SlicesPerPicture = ctx->ui8SlicesPerPicture;
97     ui32HalfwayBU = 0;
98     ui8HalfWaySlice=ui8SlicesPerPicture/2;
99     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: slot num = %d, aso = %d\n", __FUNCTION__, i32SlotNum, ctx->bArbitrarySO);
100     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: stream id = %d, addr = 0x%x\n", __FUNCTION__, ui32StreamIndex, ps_mem->bufs_slice_map.virtual_addr);
101 
102     psb_buffer_map(&(ps_mem->bufs_slice_map), &(ps_mem->bufs_slice_map.virtual_addr));
103     if (ps_mem->bufs_slice_map.virtual_addr == NULL) {
104         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping slice map\n", __FUNCTION__);
105         goto out1;
106     }
107 
108     pvBuffer = (unsigned char*)(ps_mem->bufs_slice_map.virtual_addr + (i32SlotNum * ctx->ctx_mem_size.slice_map));
109     if (pvBuffer == NULL) {
110         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: pvBuffer == NULL\n", __FUNCTION__);
111         goto out1;
112     }
113 
114     if (ctx->bArbitrarySO) {
115         IMG_UINT8 ui8Index;
116         IMG_UINT8 ui32FirstBUInSlice;
117         IMG_UINT8 ui8SizeInKicks;
118         IMG_UINT8 ui8TotalBUs;
119         IMG_UINT8 aui8SliceNumbers[MAX_SLICESPERPIC];
120 
121 	memset(aui8SliceNumbers, 0, MAX_SLICESPERPIC);
122 
123         ui8SlicesPerPicture = tng__rand(ctx) % ctx->ui8SlicesPerPicture + 1;
124         // Fill slice map
125         // Fill number of slices
126         * pvBuffer = ui8SlicesPerPicture;
127         pvBuffer++;
128 
129         for (ui8Index = 0; ui8Index < ui8SlicesPerPicture; ui8Index++)
130             aui8SliceNumbers[ui8Index] = ui8Index;
131 
132 	// randomise slice numbers
133         for (ui8Index = 0; ui8Index < 20; ui8Index++) {
134             IMG_UINT8 ui8FirstCandidate;
135             IMG_UINT8 ui8SecondCandidate;
136             IMG_UINT8 ui8Temp;
137 
138             ui8FirstCandidate = tng__rand(ctx) % ui8SlicesPerPicture;
139             ui8SecondCandidate = tng__rand(ctx) % ui8SlicesPerPicture;
140 
141             ui8Temp = aui8SliceNumbers[ui8FirstCandidate];
142             aui8SliceNumbers[ui8FirstCandidate] = aui8SliceNumbers[ui8SecondCandidate];
143             aui8SliceNumbers[ui8SecondCandidate] = ui8Temp;
144         }
145 
146         ui8TotalBUs = (ctx->ui16PictureHeight / 16) * (ctx->ui16Width / 16) / ctx->sRCParams.ui32BUSize;
147 
148         ui32FirstBUInSlice = 0;
149 
150         for (ui8Index = 0; ui8Index < ui8SlicesPerPicture - 1; ui8Index++) {
151             IMG_UINT32 ui32BUsCalc;
152             if (ui8Index==ui8HalfWaySlice) ui32HalfwayBU=ui32FirstBUInSlice;
153 
154             ui32BUsCalc=(ui8TotalBUs - 1 * (ui8SlicesPerPicture - ui8Index));
155             if(ui32BUsCalc)
156                 ui8SizeInKicks = tng__rand(ctx) %ui32BUsCalc  + 1;
157             else
158                 ui8SizeInKicks = 1;
159             ui8TotalBUs -= ui8SizeInKicks;
160 
161             // slice number
162             * pvBuffer = aui8SliceNumbers[ui8Index];
163             pvBuffer++;
164 
165             // SizeInKicks BU
166             * pvBuffer = ui8SizeInKicks;
167             pvBuffer++;
168             ui32FirstBUInSlice += (IMG_UINT32) ui8SizeInKicks;
169         }
170         ui8SizeInKicks = ui8TotalBUs;
171         // slice number
172         * pvBuffer = aui8SliceNumbers[ui8SlicesPerPicture - 1];
173         pvBuffer++;
174 
175         // last BU
176         * pvBuffer = ui8SizeInKicks;
177         pvBuffer++;
178     } else {
179         // Fill standard Slice Map (non arbitrary)
180         IMG_UINT8 ui8Index;
181         IMG_UINT8 ui8SliceNumber;
182         IMG_UINT8 ui32FirstBUInSlice;
183         IMG_UINT8 ui8SizeInKicks;
184         IMG_UINT32 ui32SliceHeight;
185 
186         // Fill number of slices
187         * pvBuffer = ui8SlicesPerPicture;
188         pvBuffer++;
189 
190 
191         ui32SliceHeight = (ctx->ui16PictureHeight / ctx->ui8SlicesPerPicture) & ~15;
192 
193         ui32FirstBUInSlice = 0;
194         ui8SliceNumber = 0;
195         for (ui8Index = 0; ui8Index < ui8SlicesPerPicture - 1; ui8Index++) {
196             if (ui8Index==ui8HalfWaySlice) ui32HalfwayBU=ui32FirstBUInSlice;
197             ui8SizeInKicks = ((ui32SliceHeight / 16)*(ctx->ui16Width/16))/ctx->sRCParams.ui32BUSize;
198 
199             // slice number
200             * pvBuffer = ui8SliceNumber;
201             pvBuffer++;
202             // SizeInKicks BU
203             * pvBuffer = ui8SizeInKicks;
204             pvBuffer++;
205 
206             ui8SliceNumber++;
207             ui32FirstBUInSlice += (IMG_UINT32) ui8SizeInKicks;
208         }
209         ui32SliceHeight = ctx->ui16PictureHeight - ui32SliceHeight * (ctx->ui8SlicesPerPicture - 1);
210         if (ui8Index==ui8HalfWaySlice) ui32HalfwayBU=ui32FirstBUInSlice;
211         ui8SizeInKicks = ((ui32SliceHeight / 16)*(ctx->ui16Width/16))/ctx->sRCParams.ui32BUSize;
212 
213         // slice number
214         * pvBuffer = ui8SliceNumber;    pvBuffer++;
215         // last BU
216         * pvBuffer = ui8SizeInKicks;    pvBuffer++;
217     }
218 
219 out1:
220     psb_buffer_unmap(&(ps_mem->bufs_slice_map));
221     ctx->ui32HalfWayBU[i32SlotNum] = ui32HalfwayBU;
222     drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: ui32HalfWayBU = %d\n", __FUNCTION__, ctx->ui32HalfWayBU[i32SlotNum]);
223     return ui32HalfwayBU;
224 }
225 
226 //IMG_V_GetInpCtrlBuf
tng__map_inp_ctrl_buf(context_ENC_p ctx,IMG_UINT8 ui8SlotNumber,IMG_UINT8 ** ppsInpCtrlBuf)227 static VAStatus tng__map_inp_ctrl_buf(
228     context_ENC_p ctx,
229     IMG_UINT8   ui8SlotNumber,
230     IMG_UINT8 **ppsInpCtrlBuf)
231 {
232     VAStatus vaStatus = VA_STATUS_SUCCESS;
233     context_ENC_mem* ps_mem = &(ctx->ctx_mem[0]);
234     context_ENC_mem_size *ps_mem_size = &(ctx->ctx_mem_size);
235     if (ppsInpCtrlBuf == NULL) {
236         drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: ppsInpCtrlBuf == NULL\n", __FUNCTION__);
237         return VA_STATUS_ERROR_INVALID_PARAMETER;
238     }
239 
240     *ppsInpCtrlBuf = NULL; // Not enabled
241 
242     // if enabled, return the input-control buffer corresponding to this slot
243     if (ctx->bEnableInpCtrl) {
244         vaStatus = psb_buffer_map(&(ps_mem->bufs_mb_ctrl_in_params), ppsInpCtrlBuf);
245         if (vaStatus == VA_STATUS_SUCCESS)
246             *ppsInpCtrlBuf += ui8SlotNumber * ps_mem_size->mb_ctrl_in_params;
247         else
248             psb_buffer_unmap(&(ps_mem->bufs_mb_ctrl_in_params));
249     }
250 
251     return vaStatus;
252 }
253 
tng__unmap_inp_ctrl_buf(context_ENC_p ctx,IMG_UINT8 __maybe_unused ui8SlotNumber,IMG_UINT8 ** ppsInpCtrlBuf)254 static VAStatus tng__unmap_inp_ctrl_buf(
255     context_ENC_p ctx,
256     IMG_UINT8   __maybe_unused ui8SlotNumber,
257     IMG_UINT8 **ppsInpCtrlBuf)
258 {
259     VAStatus vaStatus = VA_STATUS_SUCCESS;
260     context_ENC_mem* ps_mem = &(ctx->ctx_mem[0]);
261 
262     // if enabled, return the input-control buffer corresponding to this slot
263     if (*ppsInpCtrlBuf != NULL) {
264         psb_buffer_unmap(&(ps_mem->bufs_mb_ctrl_in_params));
265         *ppsInpCtrlBuf = NULL; // Not enabled
266     }
267     return vaStatus;
268 }
269 
270 //APP_FillInpCtrlBuf
271 #define DEFAULT_INTER_INTRA_SCALE_TBL_IDX   (0)
272 #define DEFAULT_CODED_SKIPPED_SCALE_TBL_IDX (0)
273 #define DEFAULT_INPUT_QP                    (0xF)
274 #define SIZEOF_MB_IN_CTRL_PARAM     (2)
275 
tng__fill_inp_ctrl_buf(context_ENC_p ctx,IMG_UINT8 * pInpCtrlBuf,IMG_INT16 i16IntraRefresh,IMG_INT8 * pi8QP,IMG_UINT32 __maybe_unused ui32HalfWayBU)276 static void tng__fill_inp_ctrl_buf(
277     context_ENC_p ctx,
278     IMG_UINT8 *pInpCtrlBuf,
279     IMG_INT16 i16IntraRefresh,
280     IMG_INT8* pi8QP,
281     IMG_UINT32 __maybe_unused ui32HalfWayBU)
282 {
283     IMG_PVOID   pvBuffer;
284     IMG_UINT32  ui32MBFrameWidth;
285     IMG_UINT32  ui32MBPictureHeight;
286     IMG_UINT32  ui32MBSliceHeight;
287     IMG_UINT16  ui16DefaultParam;
288     IMG_UINT16  ui16IntraParam;
289     IMG_BOOL	bRefresh=IMG_FALSE;
290     IMG_UINT32 ui32CurrentIndex;
291     IMG_UINT32 ui32MBx, ui32MBy;
292     IMG_UINT16 *pui16MBParam;
293     IMG_INT8	i8QPInit;
294     IMG_INT8	i8QP;
295     IMG_INT8	iMaxQP;
296 
297 #ifdef BRN_30324
298     IMG_UINT32 ui32HalfWayMB=ui32HalfWayBU * ctx->sRCParams.ui32BUSize;
299 #endif
300 
301     if (pi8QP == NULL) {
302         drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: start QP == NULL\n", __FUNCTION__);
303         return ;
304     }
305 
306     drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: start QP = %d\n", __FUNCTION__, *pi8QP);
307 
308     if (i16IntraRefresh > 0) {
309         bRefresh=IMG_TRUE;
310     }
311 
312     iMaxQP = 31;
313     if (ctx->eStandard == IMG_STANDARD_H264) {
314         iMaxQP = 51;
315     }
316     if(pi8QP) {
317         i8QPInit = * pi8QP;
318     } else {
319         i8QPInit = DEFAULT_INPUT_QP;
320     }
321     // get the buffer
322     // IMG_C_GetBuffer(psActiveContext->hContext, pInpCtrlBuf, &pvBuffer,IMG_TRUE);
323     pvBuffer = (IMG_PVOID) pInpCtrlBuf;
324 
325     //fill data
326     ui32MBFrameWidth  = (ctx->ui16Width/16);
327     ui32MBPictureHeight = (ctx->ui16PictureHeight/16);
328     ui32MBSliceHeight = (ui32MBPictureHeight/ctx->ui8SlicesPerPicture);
329 
330     pui16MBParam = (IMG_UINT16 *)pvBuffer;
331     ui32CurrentIndex=0;
332 
333     for(ui32MBy = 0; ui32MBy < (IMG_UINT32)(ctx->ui16PictureHeight / 16); ui32MBy++) {
334         for(ui32MBx = 0; ui32MBx < ui32MBFrameWidth; ui32MBx++) {
335             IMG_UINT16 ui16MBParam = 0;
336 
337 #ifdef BRN_30324
338             if (ui32HalfWayMB && ui32CurrentIndex == ui32HalfWayMB)
339                 if (ctx->ui8SlicesPerPicture > 1 && ctx->i32NumPipes > 1) {
340                     ui32CurrentIndex=(((ui32CurrentIndex)+31)&(~31));
341                 }
342 #endif
343             i8QP = i8QPInit + ((tng__rand(ctx)%6)-3);
344             i8QP = tng__max(tng__min(i8QP, iMaxQP), ctx->sRCParams.iMinQP);
345 
346             ui16DefaultParam = ( i8QP<<10) | (3 <<7) |(3<<4);
347             ui16IntraParam =  ( i8QP<<10)	| (0 <<7) |(0<<4);
348 
349             ui16MBParam = ui16DefaultParam;
350             if (bRefresh) {
351                 if ((IMG_INT32)ui32CurrentIndex > ctx->i32LastCIRIndex) {
352                     ctx->i32LastCIRIndex = ui32CurrentIndex;
353                     ui16MBParam = ui16IntraParam;
354                     i16IntraRefresh--;
355                     if(i16IntraRefresh <= 0)
356                         bRefresh = IMG_FALSE;
357                 }
358             }
359             pui16MBParam[ui32CurrentIndex++] = ui16MBParam;
360         }
361     }
362 
363     if (bRefresh) {
364         ctx->i32LastCIRIndex = -1;
365         while (i16IntraRefresh) {
366             i8QP = i8QPInit + ((tng__rand(ctx)%6)-3);
367             i8QP = tng__max(tng__min(i8QP, iMaxQP), ctx->sRCParams.iMinQP);
368             ui16IntraParam = ( i8QP<<10) |(0 <<7) |(0<<4);
369             pui16MBParam[++ctx->i32LastCIRIndex] = ui16IntraParam;
370             i16IntraRefresh--;
371         }
372     }
373 
374     drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: end QP = %d\n", __FUNCTION__, *pi8QP);
375     //release buffer
376     //IMG_C_ReleaseBuffer(psActiveContext->hContext, pInpCtrlBuf,IMG_TRUE);
377     return ;
378 }
379 
380 /***********************************************************************************
381  * Function Name     : APP_FillInputControl
382  * Inputs                   : psContext
383  * Description           : Fills input control buffer for a given source picture
384  ************************************************************************************/
tng__fill_input_control(context_ENC_p ctx,IMG_UINT8 ui8SlotNum,IMG_UINT32 __maybe_unused ui32HalfWayBU)385 static void tng__fill_input_control(
386     context_ENC_p ctx,
387     IMG_UINT8 ui8SlotNum,
388     IMG_UINT32 __maybe_unused ui32HalfWayBU)
389 {
390     IMG_UINT8 * pInpCtrlBuf = NULL;
391     IMG_INT8 i8InitialQp = ctx->sRCParams.ui32InitialQp;
392     // Get pointer to MB Control buffer for current source buffer (if input control is enabled, otherwise buffer is NULL)
393     // Please refer to kernel tng_setup_cir_buf()
394     /*
395     tng__map_inp_ctrl_buf(ctx, ui8SlotNum, &pInpCtrlBuf);
396     if (pInpCtrlBuf!= IMG_NULL) {
397         tng__fill_inp_ctrl_buf(ctx, pInpCtrlBuf,(IMG_INT16)(ctx->ui16IntraRefresh), &i8InitialQp, ui32HalfWayBU);
398     }
399     tng__unmap_inp_ctrl_buf(ctx, ui8SlotNum, &pInpCtrlBuf);
400     */
401     tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID,
402         MTX_CMDID_SW_FILL_INPUT_CTRL, ui8SlotNum, 0, 0);
403 
404     return ;
405 }
406 
tng__send_air_inp_ctrl_buf(context_ENC_p ctx,IMG_INT8 * pInpCtrlBuf)407 static void tng__send_air_inp_ctrl_buf(context_ENC_p ctx, IMG_INT8 *pInpCtrlBuf)
408 {
409     //IMG_PVOID pvICBuffer;
410     IMG_UINT16 ui16IntraParam;
411     //IMG_BOOL bRefresh = IMG_FALSE;
412     IMG_UINT32 ui32CurrentCnt, ui32SentCnt;
413     IMG_UINT32 ui32MBMaxSize;
414     IMG_UINT16 *pui16MBParam;
415     IMG_UINT32 ui32NewScanPos, ui32Skip;
416 
417 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
418     IMG_CHAR TmpOutputTble[396]; //Debug only
419 #endif
420     ui16IntraParam = (0 << 7) | (0 << 4);
421 
422     if (ctx->ui32FrameCount[0] < 1)
423         return;
424 
425     // get the buffer
426     pui16MBParam = (IMG_UINT16 *) pInpCtrlBuf;
427 
428     //fill data
429     ui32MBMaxSize = (IMG_UINT32)(ctx->ui16PictureHeight / 16) * (IMG_UINT32)(ctx->ui16Width / 16);
430     ui32CurrentCnt = 0;
431     if (ctx->sAirInfo.i16AIRSkipCnt >= 0)
432         ui32Skip = ctx->sAirInfo.i16AIRSkipCnt;
433     else
434         //ui32Skip=APP_Rand() % psActiveContext->sAirInfo.i32NumAIRSPerFrame; // Pseudorandom skip.
435         ui32Skip = (ctx->ui32FrameCount[0] & 0x7) + 1; // Pseudorandom skip.
436 
437 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
438         {
439             IMG_UINT32 tsp;
440             if (fp)
441             {
442                 fp = fopen("SADvals.txt", "a");
443             }
444             else
445             {
446                 fp = fopen("SADvals.txt", "w");
447             }
448 
449             fprintf(fp, "\n---------------------------------------------------------------------------\n");
450             fprintf(fp, "SENDING SADvals  (skip:%i)\n", ui32Skip);
451 
452             for (tsp = 0; tsp < ui32MBMaxSize; tsp++)
453             {
454                 if (ctx->sAirInfo.pi8AIR_Table[tsp] > 0)
455                 {
456                     TmpOutputTble[tsp] = 'x';
457                 }
458                 else
459                 {
460                     TmpOutputTble[tsp] = 'o';
461                 }
462             }
463         }
464 #endif
465 
466     ui32NewScanPos = (IMG_UINT32) (ctx->sAirInfo.ui16AIRScanPos + ui32Skip) % ui32MBMaxSize;
467     ui32CurrentCnt = ui32SentCnt = 0;
468 
469     while (ui32CurrentCnt < ui32MBMaxSize &&
470         ((ctx->sAirInfo.i32NumAIRSPerFrame == 0) ||
471         ui32SentCnt < (IMG_UINT32) ctx->sAirInfo.i32NumAIRSPerFrame)) {
472         IMG_UINT16 ui16MBParam;
473 
474         if (ctx->sAirInfo.pi8AIR_Table[ui32NewScanPos] >= 0) {
475             // Mark the entry as 'touched'
476             ctx->sAirInfo.pi8AIR_Table[ui32NewScanPos] = -1 - ctx->sAirInfo.pi8AIR_Table[ui32NewScanPos];
477 
478             if (ctx->sAirInfo.pi8AIR_Table[ui32NewScanPos] < -1) {
479                 ui16MBParam = pui16MBParam[ui32NewScanPos] & (0xFF << 10);
480                 ui16MBParam |= ui16IntraParam;
481                 pui16MBParam[ui32NewScanPos] = ui16MBParam;
482                 ctx->sAirInfo.pi8AIR_Table[ui32NewScanPos]++;
483 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
484                 TmpOutputTble[ui32NewScanPos]='I';
485 #endif
486                 ui32NewScanPos += ui32Skip;
487                 ui32SentCnt++;
488             }
489             ui32CurrentCnt++;
490         }
491 
492         ui32NewScanPos++;
493         ui32NewScanPos = ui32NewScanPos % ui32MBMaxSize;
494         if (ui32NewScanPos == ctx->sAirInfo.ui16AIRScanPos) {
495             /* we have looped around */
496             break;
497         }
498     }
499 
500     ctx->sAirInfo.ui16AIRScanPos = ui32NewScanPos;
501 
502 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
503         {
504             IMG_UINT32 tsp;
505             for (tsp = 0; tsp < ui32MBMaxSize; tsp++)
506             {
507                 if (tsp % ((IMG_UINT32)(ctx->ui16Width/16)) == 0)
508                 {
509                     fprintf(fp, "\n%c", TmpOutputTble[tsp]);
510                 }
511                 else
512                 {
513                     fprintf(fp, "%c", TmpOutputTble[tsp]);
514                 }
515             }
516 
517             fprintf(fp, "\n---------------------------------------------------------------------------\n");
518             fclose(fp);
519         }
520 #endif
521 
522     drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: end\n", __FUNCTION__);
523     return ;
524 }
525 
526 // Adaptive Intra Refresh (AIR) - send the AIR values to the next bufferk
527 // APP_UpdateAdaptiveIntraRefresh_Send
tng__update_air_send(context_ENC_p ctx,IMG_UINT8 ui8SlotNum)528 static void tng__update_air_send(context_ENC_p ctx, IMG_UINT8 ui8SlotNum)
529 {
530     IMG_UINT8 *pInpCtrlBuf = NULL;
531     drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: start\n", __FUNCTION__);
532     // Get pointer to MB Control buffer for current source buffer (if input control is enabled, otherwise buffer is NULL)
533 #if 0
534     tng__map_inp_ctrl_buf(ctx, ui8SlotNum, &pInpCtrlBuf);
535     if(pInpCtrlBuf!= IMG_NULL) {
536         tng__send_air_inp_ctrl_buf(ctx, (IMG_INT8 *)pInpCtrlBuf);
537     }
538     tng__unmap_inp_ctrl_buf(ctx, ui8SlotNum, &pInpCtrlBuf);
539     drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: end\n", __FUNCTION__);
540 #endif
541     tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID,
542         MTX_CMDID_SW_UPDATE_AIR_SEND, ui8SlotNum, 0, 0);
543     return ;
544 }
545 
546 /***********************************************************************************
547  * Function Name     : functions for output control
548  ************************************************************************************/
549 //IMG_V_GetFirstPassOutBuf
tng__map_first_pass_out_buf(context_ENC_p ctx,IMG_UINT8 __maybe_unused ui8SlotNumber,IMG_UINT8 ** ppsFirstPassOutBuf)550 VAStatus tng__map_first_pass_out_buf(
551     context_ENC_p ctx,
552     IMG_UINT8   __maybe_unused ui8SlotNumber,
553     IMG_UINT8 **ppsFirstPassOutBuf)
554 {
555     VAStatus vaStatus = VA_STATUS_SUCCESS;
556     context_ENC_mem* ps_mem = &(ctx->ctx_mem[0]);
557 
558     if (ppsFirstPassOutBuf == NULL) {
559         drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: ppsFirstPassOutBuf == NULL\n", __FUNCTION__);
560         return VA_STATUS_ERROR_INVALID_PARAMETER;
561     }
562 
563     *ppsFirstPassOutBuf = NULL; // Not enabled
564 
565     // if enabled, return the input-control buffer corresponding to this slot
566     if (ctx->bEnableInpCtrl) {
567          vaStatus = psb_buffer_map(&(ps_mem->bufs_first_pass_out_params), ppsFirstPassOutBuf);
568         if (vaStatus != VA_STATUS_SUCCESS)
569             psb_buffer_unmap(&(ps_mem->bufs_first_pass_out_params));
570     }
571 
572     return vaStatus;
573 }
574 
tng__unmap_first_pass_out_buf(context_ENC_p ctx,IMG_UINT8 __maybe_unused ui8SlotNumber,IMG_UINT8 ** ppsFirstPassOutBuf)575 VAStatus tng__unmap_first_pass_out_buf(
576     context_ENC_p ctx,
577     IMG_UINT8 __maybe_unused ui8SlotNumber,
578     IMG_UINT8 **ppsFirstPassOutBuf)
579 {
580     VAStatus vaStatus = VA_STATUS_SUCCESS;
581     context_ENC_mem* ps_mem = &(ctx->ctx_mem[0]);
582 
583     // if enabled, return the input-control buffer corresponding to this slot
584     if (*ppsFirstPassOutBuf != NULL) {
585         psb_buffer_unmap(&(ps_mem->bufs_first_pass_out_params));
586         *ppsFirstPassOutBuf = NULL; // Not enabled
587     }
588 
589     return vaStatus;
590 }
591 
592 //IMG_V_GetBestMBDecisionOutBuf
tng__map_best_mb_decision_out_buf(context_ENC_p ctx,IMG_UINT8 __maybe_unused ui8SlotNumber,IMG_UINT8 ** ppsBestMBDecisionOutBuf)593 VAStatus tng__map_best_mb_decision_out_buf(
594     context_ENC_p ctx,
595     IMG_UINT8   __maybe_unused ui8SlotNumber,
596     IMG_UINT8  **ppsBestMBDecisionOutBuf)
597 {
598     VAStatus vaStatus = VA_STATUS_SUCCESS;
599     context_ENC_mem* ps_mem = &(ctx->ctx_mem[0]);
600 
601     // if enabled, return the input-control buffer corresponding to this slot
602     if (ctx->bEnableInpCtrl)
603         vaStatus = psb_buffer_map(&(ps_mem->bufs_first_pass_out_best_multipass_param), ppsBestMBDecisionOutBuf);
604     else
605         *ppsBestMBDecisionOutBuf = NULL; // Not enabled
606 
607     return vaStatus;
608 }
609 
tng__unmap_best_mb_decision_out_buf(context_ENC_p ctx,IMG_UINT8 __maybe_unused ui8SlotNumber,IMG_UINT8 ** ppsBestMBDecisionOutBuf)610 VAStatus tng__unmap_best_mb_decision_out_buf(
611     context_ENC_p ctx,
612     IMG_UINT8   __maybe_unused ui8SlotNumber,
613     IMG_UINT8  **ppsBestMBDecisionOutBuf)
614 {
615     VAStatus vaStatus = VA_STATUS_SUCCESS;
616     context_ENC_mem* ps_mem = &(ctx->ctx_mem[0]);
617 
618     // if enabled, return the input-control buffer corresponding to this slot
619     if (*ppsBestMBDecisionOutBuf != NULL) {
620         psb_buffer_unmap(&(ps_mem->bufs_first_pass_out_best_multipass_param));
621         *ppsBestMBDecisionOutBuf = NULL; // Not enabled
622      }
623 
624     return vaStatus;
625 }
626 
627 // Calculate Adaptive Intra Refresh (AIR)
tng__calc_air_inp_ctrl_buf(context_ENC_p ctx,IMG_UINT8 * pFirstPassOutBuf,IMG_UINT8 * pBestMBDecisionCtrlBuf)628 static void tng__calc_air_inp_ctrl_buf(context_ENC_p ctx, IMG_UINT8 *pFirstPassOutBuf, IMG_UINT8 *pBestMBDecisionCtrlBuf)
629 {
630     IMG_UINT8 *pSADPointer;
631     IMG_UINT8 *pvSADBuffer;
632     IMG_UINT8 ui8IsAlreadyIntra;
633     IMG_UINT32 ui32MBFrameWidth;
634     IMG_UINT32 ui32MBPictureHeight;
635     IMG_UINT16 ui16IntraParam;
636     IMG_UINT32 ui32MBx, ui32MBy;
637     IMG_UINT32 ui32SADParam;
638     IMG_UINT32 ui32tSAD_Threshold, ui32tSAD_ThresholdLo, ui32tSAD_ThresholdHi;
639     IMG_UINT32 ui32MaxMBs, ui32NumMBsOverThreshold, ui32NumMBsOverLo, ui32NumMBsOverHi;
640     IMG_BEST_MULTIPASS_MB_PARAMS *psBestMB_Params;
641     IMG_FIRST_STAGE_MB_PARAMS *psFirstMB_Params;
642 
643     ui16IntraParam = (0 << 7) | (0 << 4);
644     ui32NumMBsOverThreshold = ui32NumMBsOverLo = ui32NumMBsOverHi = 0;
645     //drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: start\n", __FUNCTION__);
646 
647 //    if (psActiveContext->ui32EncodeSent < (IMG_UINT32)psActiveContext->ui8MaxSourceSlots + 1)
648 //    if (ctx->ui32FrameCount[0] < (IMG_UINT32)(ctx->ui8SlotsInUse + 1))
649 //        return;
650     drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: start\n", __FUNCTION__);
651     //fill data
652     ui32MBFrameWidth  = (ctx->ui16Width/16);
653     ui32MBPictureHeight = (ctx->ui16PictureHeight/16);
654 
655     // get the SAD results buffer (either IPE0 and IPE1 results or, preferably, the more accurate Best Multipass SAD results)
656     if (pBestMBDecisionCtrlBuf) {
657         pvSADBuffer = pBestMBDecisionCtrlBuf;
658         drv_debug_msg(VIDEO_DEBUG_GENERAL,"AIR active: Using Best Multipass SAD values ");
659 
660 //#ifdef  MULTIPASS_MV_PLACEMENT_ISSUE_FIXED
661 	if ((ctx->ui8EnableSelStatsFlags & ESF_MP_BEST_MOTION_VECTOR_STATS))
662 //#endif
663 	{
664             // The actual Param structures (which contain SADs) are located after the Multipass Motion Vector entries
665 	    pvSADBuffer += (ui32MBPictureHeight * (ui32MBFrameWidth) * sizeof(IMG_BEST_MULTIPASS_MB_PARAMS_IPMV));
666         }
667     } else {
668         pvSADBuffer = pFirstPassOutBuf;
669         drv_debug_msg(VIDEO_DEBUG_GENERAL,"AIR active: Using IPE SAD values ");
670     }
671 
672     if (ctx->sAirInfo.i32NumAIRSPerFrame == 0)
673         ui32MaxMBs = ui32MBFrameWidth * ui32MBPictureHeight; // Default to ALL MB's in frame
674     else if (ctx->sAirInfo.i32NumAIRSPerFrame < 0)
675         ctx->sAirInfo.i32NumAIRSPerFrame = ui32MaxMBs = ((ui32MBFrameWidth * ui32MBPictureHeight) + 99) / 100; // Default to 1% of MB's in frame (min 1)
676     else
677         ui32MaxMBs = ctx->sAirInfo.i32NumAIRSPerFrame;
678 
679     pSADPointer = (IMG_UINT8 *)pvSADBuffer;
680 
681     if (ctx->sAirInfo.i32SAD_Threshold >= 0)
682         ui32tSAD_Threshold = (IMG_UINT16)ctx->sAirInfo.i32SAD_Threshold;
683     else {
684         // Running auto adjust threshold adjust mode
685         if (ctx->sAirInfo.i32SAD_Threshold == -1) {
686             // This will occur only the first time
687             if (pBestMBDecisionCtrlBuf) {
688                 psBestMB_Params=(IMG_BEST_MULTIPASS_MB_PARAMS *) pSADPointer; // Auto seed the threshold with the first value
689                 ui32SADParam = psBestMB_Params->ui32SAD_Inter_MBInfo & IMG_BEST_MULTIPASS_SAD_MASK;
690             } else {
691                 psFirstMB_Params=(IMG_FIRST_STAGE_MB_PARAMS *) pSADPointer; // Auto seed the threshold with the first value
692                 ui32SADParam = (IMG_UINT32) psFirstMB_Params->ui16Ipe0Sad;
693             }
694             ctx->sAirInfo.i32SAD_Threshold = -1 - ui32SADParam; // Negative numbers indicate auto-adjusting threshold
695         }
696         ui32tSAD_Threshold = (IMG_UINT32) - (ctx->sAirInfo.i32SAD_Threshold + 1);
697     }
698 
699     ui32tSAD_ThresholdLo = ui32tSAD_Threshold / 2;
700     ui32tSAD_ThresholdHi = ui32tSAD_Threshold + ui32tSAD_ThresholdLo;
701 
702     drv_debug_msg(VIDEO_DEBUG_GENERAL,"Th:%u, MaxMbs:%u, Skp:%i\n", (unsigned int)ui32tSAD_Threshold, (unsigned int)ui32MaxMBs, ctx->sAirInfo.i16AIRSkipCnt);
703 
704 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
705 	if (fp)
706 		fp=fopen("SADvals.txt","a");
707 	else
708 		fp=fopen("SADvals.txt","w");
709 
710 	if (ctx->sAirInfo.i32SAD_Threshold>=0)
711 		if (ctx->sAirInfo.i32NumAIRSPerFrame>0)
712 			fprintf(fp, "S_SADThreshold: %i	MaxMBs: %i\n", ui32tSAD_Threshold, ui32MaxMBs);
713 		else
714 			fprintf(fp, "S_SADThreshold: %i	MaxMBs: NA\n", ui32tSAD_Threshold, ui32MaxMBs);
715 	else
716 		fprintf(fp, "V_SADThreshold: %i	MaxMBs: %i\n", ui32tSAD_Threshold, ui32MaxMBs);
717 
718 	if (pBestMBDecisionCtrlBuf)
719 		fprintf(fp, "Using Best Multipass SAD values\n");
720 	else
721 		fprintf(fp, "Using Motion Search Data IPE SAD values\n");
722 #endif
723 
724     // This loop could be optimised to a single counter if necessary, retaining for clarity
725     for (ui32MBy = 0; ui32MBy < ui32MBPictureHeight; ui32MBy++) {
726         for( ui32MBx=0; ui32MBx<ui32MBFrameWidth; ui32MBx++) {
727 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
728             IMG_CHAR cMarked;
729             cMarked='_';
730 #endif
731             // Turn all negative table values to positive (reset 'touched' state of a block that may have been set in APP_SendAIRInpCtrlBuf())
732 	    if (ctx->sAirInfo.pi8AIR_Table[ui32MBy *  ui32MBFrameWidth + ui32MBx] < 0)
733                 ctx->sAirInfo.pi8AIR_Table[ui32MBy *  ui32MBFrameWidth + ui32MBx] = -1 - ctx->sAirInfo.pi8AIR_Table[ui32MBy *  ui32MBFrameWidth + ui32MBx];
734 
735             // This will read the SAD value from the buffer (either IPE0 SAD or the superior Best multipass parameter structure SAD value)
736             if (pBestMBDecisionCtrlBuf) {
737                 psBestMB_Params = (IMG_BEST_MULTIPASS_MB_PARAMS *) pSADPointer;
738                 ui32SADParam = psBestMB_Params->ui32SAD_Inter_MBInfo & IMG_BEST_MULTIPASS_SAD_MASK;
739 
740                 if ((psBestMB_Params->ui32SAD_Intra_MBInfo & IMG_BEST_MULTIPASS_MB_TYPE_MASK) >> IMG_BEST_MULTIPASS_MB_TYPE_SHIFT == 1)
741                     ui8IsAlreadyIntra = 1;
742                 else
743                     ui8IsAlreadyIntra = 0;
744 
745                 pSADPointer=(IMG_UINT8 *) &(psBestMB_Params[1]);
746             } else {
747                 psFirstMB_Params=(IMG_FIRST_STAGE_MB_PARAMS *) pSADPointer;
748                 ui32SADParam = (IMG_UINT32) psFirstMB_Params->ui16Ipe0Sad;
749                 ui32SADParam += (IMG_UINT32) psFirstMB_Params->ui16Ipe1Sad;
750                 ui32SADParam /= 2;
751                 ui8IsAlreadyIntra = 0; // We don't have the information to determine this
752                 pSADPointer=(IMG_UINT8 *) &(psFirstMB_Params[1]);
753             }
754 
755             if (ui32SADParam >= ui32tSAD_ThresholdLo) {
756                 ui32NumMBsOverLo++;
757 
758                 if (ui32SADParam >= ui32tSAD_Threshold) {
759 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
760                     cMarked='i';
761 #endif
762 
763                     // if (!ui8IsAlreadyIntra) // Don't mark this block if it's just been encoded as an Intra block anyway
764                     // (results seem better without this condition anyway)
765                     {
766                         ctx->sAirInfo.pi8AIR_Table[ui32MBy *  ui32MBFrameWidth + ui32MBx]++;
767 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
768                         cMarked='I';
769 #endif
770                     }
771                     ui32NumMBsOverThreshold++;
772                     if (ui32SADParam >= ui32tSAD_ThresholdHi)
773                         ui32NumMBsOverHi++;
774                 }
775             }
776 
777 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
778             fprintf(fp,"%4x[%i]%c,	",ui32SADParam, ctx->sAirInfo.pi8AIR_Table[ui32MBy * ui32MBFrameWidth + ui32MBx], cMarked);
779 #endif
780         }
781         pSADPointer=(IMG_UINT8 *) ALIGN_64(((IMG_UINT32) pSADPointer));
782 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
783 	fprintf(fp,"\n");
784 #endif
785     }
786 
787     // Test and process running adaptive threshold case
788     if (ctx->sAirInfo.i32SAD_Threshold < 0) {
789         // Adjust our threshold (to indicate it's auto-adjustable store it as a negative value minus 1)
790         if (ui32NumMBsOverLo <= ui32MaxMBs)
791             ctx->sAirInfo.i32SAD_Threshold = (IMG_INT32) - ((IMG_INT32)ui32tSAD_ThresholdLo) - 1;
792         else
793             if (ui32NumMBsOverHi >= ui32MaxMBs)
794                 ctx->sAirInfo.i32SAD_Threshold = (IMG_INT32) - ((IMG_INT32)ui32tSAD_ThresholdHi) - 1;
795             else {
796                 if (ui32MaxMBs < ui32NumMBsOverThreshold) {
797                     ctx->sAirInfo.i32SAD_Threshold = ((IMG_INT32)ui32tSAD_ThresholdHi - (IMG_INT32)ui32tSAD_Threshold);
798                     ctx->sAirInfo.i32SAD_Threshold *= ((IMG_INT32)ui32MaxMBs - (IMG_INT32)ui32NumMBsOverThreshold);
799                     ctx->sAirInfo.i32SAD_Threshold /= ((IMG_INT32)ui32NumMBsOverHi - (IMG_INT32)ui32NumMBsOverThreshold);
800                     ctx->sAirInfo.i32SAD_Threshold += ui32tSAD_Threshold;
801                 } else {
802                     ctx->sAirInfo.i32SAD_Threshold = ((IMG_INT32)ui32tSAD_Threshold - (IMG_INT32)ui32tSAD_ThresholdLo);
803                     ctx->sAirInfo.i32SAD_Threshold *= ((IMG_INT32)ui32MaxMBs - (IMG_INT32)ui32NumMBsOverLo);
804                     ctx->sAirInfo.i32SAD_Threshold /= ((IMG_INT32)ui32NumMBsOverThreshold - (IMG_INT32)ui32NumMBsOverLo);
805                     ctx->sAirInfo.i32SAD_Threshold += ui32tSAD_ThresholdLo;
806                 }
807                 ctx->sAirInfo.i32SAD_Threshold = -ctx->sAirInfo.i32SAD_Threshold - 1;
808             }
809 
810 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
811             fprintf(fp,"THRESHOLDS ADJUSTMENT\nThrLo:%i	ThrMid:%i	ThrHi:%i\nMBsLo:%i	MBsMid:%i	MBsHi:%i\n",ui32tSAD_ThresholdLo, ui32tSAD_Threshold, ui32tSAD_ThresholdHi, ui32NumMBsOverLo, ui32NumMBsOverThreshold, ui32NumMBsOverHi);
812             fprintf(fp,"Target No. MB's:%i\nThreshold adjusted to: %i\n",ui32MaxMBs, -(ctx->sAirInfo.i32SAD_Threshold));
813 #endif
814     }
815 
816 #ifdef ADAPTIVE_INTRA_REFRESH_DEBUG_OUTPUT
817     fprintf(fp,"\n MBs tagged:%i\n", ui32NumMBsOverThreshold);
818     fclose(fp);
819 #endif
820     drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: end\n", __FUNCTION__);
821     return;
822 }
823 
824 // Adaptive Intra Refresh (AIR) - Calculate the new AIR values based upon Motion Search feedback
825 // APP_UpdateAdaptiveIntraRefresh_Calc
tng_update_air_calc(context_ENC_p ctx,IMG_UINT8 ui8SlotNum)826 static void tng_update_air_calc(context_ENC_p ctx, IMG_UINT8 ui8SlotNum)
827 {
828     IMG_UINT8  *pFirstPassOutBuf = NULL;
829     IMG_UINT8  *pBestMBDecisionCtrlBuf = NULL;
830 #if 0
831     // Get pointer to MB Control buffer for current source buffer (if input control is enabled, otherwise buffer is NULL)
832     tng__map_first_pass_out_buf(ctx, ui8SlotNum, &pFirstPassOutBuf);
833     tng__map_best_mb_decision_out_buf(ctx, ui8SlotNum, &pBestMBDecisionCtrlBuf);
834 
835     if(pFirstPassOutBuf || pBestMBDecisionCtrlBuf)
836 	tng__calc_air_inp_ctrl_buf (ctx, pFirstPassOutBuf, pBestMBDecisionCtrlBuf);
837 
838     tng__unmap_first_pass_out_buf(ctx, ui8SlotNum, &pFirstPassOutBuf);
839     tng__unmap_best_mb_decision_out_buf(ctx, ui8SlotNum, &pBestMBDecisionCtrlBuf);
840 #endif
841     tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID,
842         MTX_CMDID_SW_UPDATE_AIR_CALC, ui8SlotNum, 0, 0);
843 }
844 
845 /***********************************************************************************
846  * Function Name     :
847  * Inputs                   :
848  * Description           :
849  ************************************************************************************/
tng_air_set_input_control(context_ENC_p ctx,IMG_UINT8 __maybe_unused ui8StreamID)850 void tng_air_set_input_control(context_ENC_p ctx, IMG_UINT8 __maybe_unused ui8StreamID)
851 {
852     IMG_UINT8 ui8SlotIndex = ctx->ui8SlotsCoded;
853     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: slot index = %d\n", __FUNCTION__, ctx->ui8SlotsCoded);
854     //IMG_UINT32 ui32HalfWayBU;
855     //ui32HalfWayBU = tng_fill_slice_map(ctx, ui8SlotIndex, ui8StreamID);
856 
857     ////////////////////////////// INPUT CONTROL
858     // Add input control stuff here
859     tng__fill_input_control(ctx, ui8SlotIndex, ctx->ui32HalfWayBU[ui8SlotIndex]);
860 
861     // Adaptive Intra Refresh (AIR) - send the AIR values to the next buffer
862     if (ctx->bEnableAIR)
863         tng__update_air_send(ctx, ui8SlotIndex);
864 }
865 
866 
867 /***********************************************************************************
868  * Function Name     :
869  * Inputs                   :
870  * Description           :
871  ************************************************************************************/
tng_air_set_output_control(context_ENC_p ctx,IMG_UINT8 __maybe_unused ui8StreamID)872 void tng_air_set_output_control(context_ENC_p ctx, IMG_UINT8 __maybe_unused ui8StreamID)
873 {
874     IMG_UINT8 ui8SlotIndex = ctx->ui8SlotsCoded;
875 
876     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: slot index = %d\n", __FUNCTION__, ctx->ui8SlotsCoded);
877 
878     if ((ctx->eFrameType == IMG_INTRA_IDR) ||
879         (ctx->eFrameType == IMG_INTRA_FRAME))
880         tng_air_buf_clear(ctx);
881     else
882         tng_update_air_calc(ctx, ui8SlotIndex);
883 
884     return;
885 }
886