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