Home | History | Annotate | Download | only in src
      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 (at) 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  ************************************************************************************/
     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 
     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 
     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  ************************************************************************************/
     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
     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
    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 
    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 
    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  ************************************************************************************/
    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 
    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
    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
    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 
    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
    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 
    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)
    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
    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  ************************************************************************************/
    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  ************************************************************************************/
    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