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