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  *    Elaine Wang <elaine.wang (at) intel.com>
     27  *    Zeng Li <zeng.li (at) intel.com>
     28  *
     29  */
     30 
     31 
     32 #include "psb_drv_video.h"
     33 
     34 //#include "pnw_H263ES.h"
     35 #include "pnw_hostcode.h"
     36 #include "hwdefs/topazSC_defs.h"
     37 #include "psb_def.h"
     38 #include "psb_drv_debug.h"
     39 #include "psb_cmdbuf.h"
     40 #include <stdio.h>
     41 #include "psb_output.h"
     42 #include <wsbm/wsbm_manager.h>
     43 #include "pnw_hostheader.h"
     44 
     45 #define ALIGN_TO(value, align) ((value + align - 1) & ~(align - 1))
     46 #define PAGE_ALIGN(value) ALIGN_TO(value, 4096)
     47 
     48 /*static VAStatus pnw_DetectFrameSkip(context_ENC_p ctx);*/
     49 
     50 static void pnw__update_rcdata(
     51     context_ENC_p psContext,
     52     PIC_PARAMS *psPicParams,
     53     IMG_RC_PARAMS *psRCParams);
     54 
     55 IMG_UINT32 MVEARegBase[4] = {0x13000, 0x23000, 0x33000, 0x43000}; /* From TopazSC TRM */
     56 
     57 /* H264 Zero bias */
     58 //#define ZERO_BIAS
     59 
     60 static const IMG_INT8 H263_QPLAMBDA_MAP[31] = {
     61     0, 0, 1, 1, 2,
     62     2, 3, 3, 4, 4,
     63     4, 5, 5, 5, 6,
     64     6, 6, 7, 7, 7,
     65     7, 8, 8, 8, 8,
     66     9, 9, 9, 9, 10, 10
     67 };
     68 
     69 // New MP4 Lambda table
     70 static const  IMG_INT8 MPEG4_QPLAMBDA_MAP[31] = {
     71     0,  0,  1,  2,  3,
     72     3,  4,  4,  5,  5,
     73     6,  6,  7,  7,  8,
     74     8,  9,  9,  10, 10,
     75     11, 11, 11, 11, 12,
     76     12, 12, 12, 13, 13, 13
     77 };
     78 
     79 // new H.264 Lambda
     80 static const IMG_INT8 H264_QPLAMBDA_MAP[40] = {
     81     2, 2, 2, 2, 3, 3, 4, 4,
     82     4, 5, 5, 5, 5, 5, 6, 6,
     83     6, 7, 7, 7, 8, 8, 9, 11,
     84     13, 14, 15, 17, 20, 23, 27, 31,
     85     36, 41, 51, 62, 74, 79, 85, 91
     86 };
     87 
     88 static const IMG_INT16 H264_InterIntraBias[27] =
     89 {
     90     20,20,20,20,20,20,50,
     91     20,20,20,20,20,20,
     92     20,25,30,45,80,140,
     93     200,300,400,500,550,
     94     600,650,700
     95 };
     96 
     97 /*static IMG_INT16 H264InterBias(IMG_INT8 i8QP)
     98 {
     99     if (i8QP >= 44)
    100         return 600;
    101     else if (i8QP <= 35)
    102         return 20;
    103 
    104     return (70 * (i8QP - 35));
    105 }*/
    106 static IMG_INT16 H264InterBias(IMG_INT8 i8QP)
    107 {
    108     if (i8QP > 1)
    109          i8QP = 1;
    110     else if (i8QP > 51)
    111         return 51;
    112 
    113     return H264_InterIntraBias[(i8QP + 1)>>1];
    114 }
    115 
    116 
    117 static IMG_INT16 H264SkipBias(IMG_INT8 i8QP, TH_SKIP_SCALE eSkipScale)
    118 {
    119     IMG_INT16 i16Lambda;
    120 
    121     // pull out lambda from the table
    122     i16Lambda = i8QP - 12;
    123     i16Lambda = (i16Lambda < 0) ? 0 : i16Lambda;
    124     i16Lambda = H264_QPLAMBDA_MAP[i16Lambda];
    125 
    126     // now do the multiplication to avoid using the actual multiply we will do this with shifts and adds/subtractions it is probable that the compiler would
    127     // pick up the multiply and optimise appropriatly but we aren't sure
    128     // * 12 = 8 + *4
    129     switch (eSkipScale) {
    130     default:
    131     case TH_SKIP_0:
    132         i16Lambda = 0;
    133         break;
    134     case TH_SKIP_24:                /* iLambda * 24 == iLambda * 2 * 12   */
    135         i16Lambda <<= 1;
    136         /* break deliberatly not used as we want to apply skip12 to skip24*/
    137     case TH_SKIP_12: /*    iLambda * 12 == iLambda * (8 + 4) == (iLambda * 8) + (iLambda * 4)  == (iLambda << 3) + (iLambda <<2)   */
    138         i16Lambda = (i16Lambda << 3) + (i16Lambda << 2);
    139     }
    140     return i16Lambda;
    141 }
    142 
    143 static IMG_INT16 H264Intra4x4Bias(IMG_INT8 i8QP)
    144 {
    145     IMG_INT16 i16Lambda;
    146 
    147     // pull out lambda from the table
    148     i16Lambda = i8QP - 12;
    149     i16Lambda = (i16Lambda < 0) ? 0 : i16Lambda;
    150     i16Lambda = H264_QPLAMBDA_MAP[i16Lambda];
    151 
    152     i16Lambda *= 120;
    153     return i16Lambda;
    154 }
    155 
    156 static int CalculateDCScaler(IMG_INT iQP, IMG_BOOL bChroma)
    157 {
    158     IMG_INT     iDCScaler;
    159     if (!bChroma) {
    160         if (iQP > 0 && iQP < 5) {
    161             iDCScaler = 8;
    162         } else if (iQP > 4 &&     iQP     < 9) {
    163             iDCScaler = 2 * iQP;
    164         } else if (iQP > 8 &&     iQP     < 25) {
    165             iDCScaler = iQP + 8;
    166         } else {
    167             iDCScaler = 2 * iQP - 16;
    168         }
    169     } else {
    170         if (iQP > 0 && iQP < 5) {
    171             iDCScaler = 8;
    172         } else if (iQP > 4 &&     iQP     < 25) {
    173             iDCScaler = (iQP + 13) / 2;
    174         } else {
    175             iDCScaler = iQP - 6;
    176         }
    177     }
    178     return iDCScaler;
    179 }
    180 
    181 static void LoadMPEG4Bias(
    182     pnw_cmdbuf_p cmdbuf,
    183     IMG_INT32 i32Core,
    184     IMG_UINT8 __maybe_unused ui8THSkip
    185 )
    186 {
    187     IMG_INT16 n;
    188     IMG_INT16 iX;
    189     IMG_UINT32 ui32RegVal;
    190     IMG_UINT8                       uiDCScaleL, uiDCScaleC, uiLambda;
    191     IMG_INT32 uIPESkipVecBias, iInterMBBias, uSPESkipVecBias, iIntra16Bias;
    192     IMG_UINT32 count = 0, cmd_word = 0;
    193     uint32_t *pCount;
    194 
    195     cmd_word = ((MTX_CMDID_SW_WRITEREG & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
    196                ((i32Core & MTX_CMDWORD_CORE_MASK) <<  MTX_CMDWORD_CORE_SHIFT);
    197     *cmdbuf->cmd_idx++ = cmd_word;
    198     pCount = cmdbuf->cmd_idx;
    199     cmdbuf->cmd_idx++;
    200 
    201     // this should be done for each core....
    202     pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_ZERO_THRESH, SPE_ZERO_THRESHOLD);
    203     for (n = 31; n > 0; n--) {
    204         iX = n - 12;
    205         if (iX < 0) {
    206             iX = 0;
    207         }
    208         // Dont Write QP Values To ESB -- IPE will write these values
    209         // Update the quantization parameter which includes doing Lamda and the Chroma QP
    210 
    211         uiDCScaleL      = CalculateDCScaler(n, IMG_FALSE);
    212         uiDCScaleC      = CalculateDCScaler(n, IMG_TRUE);
    213         uiLambda        = MPEG4_QPLAMBDA_MAP[n - 1];
    214 
    215         ui32RegVal = uiDCScaleL;
    216         ui32RegVal |= (uiDCScaleC) << 8;
    217         ui32RegVal |= (uiLambda) << 16;
    218         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, ui32RegVal);
    219 
    220 
    221         uIPESkipVecBias = TH_SKIP_IPE * uiLambda;
    222         iInterMBBias            = TH_INTER * (n - TH_INTER_QP);
    223         if (iInterMBBias < 0)
    224             iInterMBBias    = 0;
    225         if (iInterMBBias > TH_INTER_MAX_LEVEL)
    226             iInterMBBias    = TH_INTER_MAX_LEVEL;
    227         uSPESkipVecBias = TH_SKIP_SPE * uiLambda;
    228         iIntra16Bias = 0;
    229 
    230         if (n & 1) {
    231             pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, uIPESkipVecBias);
    232             pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, uIPESkipVecBias);
    233             pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, iIntra16Bias);
    234             pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, iInterMBBias);
    235         }
    236     }
    237     *pCount = count;
    238 }
    239 
    240 static void LoadH263Bias(
    241     pnw_cmdbuf_p cmdbuf, IMG_INT32 i32Core, IMG_UINT8 __maybe_unused ui8THSkip)
    242 {
    243     IMG_INT16 n;
    244     IMG_INT16 iX;
    245     IMG_UINT32 ui32RegVal;
    246     IMG_UINT8                       uiDCScaleL, uiDCScaleC, uiLambda;
    247     IMG_INT32 uIPESkipVecBias, iInterMBBias, uSPESkipVecBias, iIntra16Bias;
    248     IMG_UINT32 count = 0, cmd_word = 0;
    249     uint32_t *pCount;
    250 
    251     cmd_word = ((MTX_CMDID_SW_WRITEREG & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
    252                ((i32Core & MTX_CMDWORD_CORE_MASK) <<  MTX_CMDWORD_CORE_SHIFT);
    253     *cmdbuf->cmd_idx++ = cmd_word;
    254     pCount = cmdbuf->cmd_idx;
    255     cmdbuf->cmd_idx++;
    256 
    257 
    258     // this should be done for each core....
    259     pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_ZERO_THRESH, SPE_ZERO_THRESHOLD);
    260     for (n = 31; n > 0; n--) {
    261         iX = n - 12;
    262         if (iX < 0) {
    263             iX = 0;
    264         }
    265         // Dont Write QP Values To ESB -- IPE will write these values
    266         // Update the quantization parameter which includes doing Lamda and the Chroma QP
    267 
    268         uiDCScaleL      = CalculateDCScaler(n, IMG_FALSE);
    269         uiDCScaleC      = CalculateDCScaler(n, IMG_TRUE);
    270         uiLambda        = H263_QPLAMBDA_MAP[n - 1];
    271 
    272         ui32RegVal = uiDCScaleL;
    273         ui32RegVal |= (uiDCScaleC) << 8;
    274         ui32RegVal |= (uiLambda) << 16;
    275 
    276         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, ui32RegVal);
    277 
    278 
    279         uIPESkipVecBias = TH_SKIP_IPE * uiLambda;
    280         iInterMBBias            = TH_INTER * (n - TH_INTER_QP);
    281         if (iInterMBBias < 0)
    282             iInterMBBias    = 0;
    283         if (iInterMBBias > TH_INTER_MAX_LEVEL)
    284             iInterMBBias    = TH_INTER_MAX_LEVEL;
    285         uSPESkipVecBias = TH_SKIP_SPE * uiLambda;
    286         iIntra16Bias = 0;
    287         //
    288         if (n & 1) {
    289             pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, uIPESkipVecBias);
    290             pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, uIPESkipVecBias);
    291             pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, iIntra16Bias);
    292             pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, iInterMBBias);
    293         }
    294     }
    295     *pCount = count;
    296 }
    297 
    298 static void LoadH264Bias(
    299     pnw_cmdbuf_p cmdbuf, IMG_INT32 i32Core, IMG_UINT8 ui8THSkip, IMG_INT8 i8QpOff)
    300 {
    301     IMG_INT8 n;
    302     IMG_INT8 iX;
    303     IMG_UINT32 ui32RegVal;
    304     IMG_UINT32 uIPESkipVecBias, iInterMBBias, uSPESkipVecBias, iIntra16Bias;
    305     IMG_UINT32 count = 0, cmd_word = 0;
    306     uint32_t *pCount;
    307 
    308     cmd_word = ((MTX_CMDID_SW_WRITEREG & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
    309                ((i32Core & MTX_CMDWORD_CORE_MASK) <<  MTX_CMDWORD_CORE_SHIFT);
    310     *cmdbuf->cmd_idx++ = cmd_word;
    311     pCount = cmdbuf->cmd_idx;
    312     cmdbuf->cmd_idx++;
    313 
    314 
    315     IMG_BYTE PVR_QP_SCALE_CR[76] = {
    316         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    317         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
    318         12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
    319         28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36, 37, 37,
    320         37, 38, 38, 38, 39, 39, 39, 39,
    321         39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
    322     };
    323 
    324     for (n = 51; n >= 0; n--) {
    325 
    326         iX = n - 12;
    327         if (iX < 0)
    328             iX = 0;
    329 
    330         // Dont Write QP Values To ESB -- IPE will write these values
    331         // Update the quantization parameter which includes doing Lamda and the Chroma QP
    332         ui32RegVal = PVR_QP_SCALE_CR[n + 12 + i8QpOff ];
    333         ui32RegVal |= ((H264_QPLAMBDA_MAP[iX] * 24) / 16) << 8;
    334         ui32RegVal |= (H264_QPLAMBDA_MAP[iX]) << 16;
    335 
    336 #ifdef ZERO_BIAS
    337         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, (2 << 16) | F_ENCODE(3, MVEA_CR_IPE_ALPHA_OR_DC_SCALE_CHR_TABLE) | F_ENCODE(PVR_QP_SCALE_CR[n], MVEA_CR_IPE_QPC_OR_DC_SCALE_LUMA_TABLE));
    338 #else
    339         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, ui32RegVal);
    340 #endif
    341 
    342     }
    343     for (n = 52; n >= 0; n -= 2) {
    344         IMG_INT8 qp = n;
    345         if (qp > 51) qp = 51;
    346 
    347         uIPESkipVecBias = H264SkipBias(qp, ui8THSkip);
    348         iInterMBBias    = H264InterBias(qp);
    349         uSPESkipVecBias = H264SkipBias(qp, ui8THSkip);
    350         iIntra16Bias    = H264Intra4x4Bias(qp);
    351 
    352 #ifdef ZERO_BIAS
    353         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, 0);
    354         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, 0);
    355         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, 0);
    356         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, 0);
    357 #else
    358         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, uIPESkipVecBias);
    359         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, uIPESkipVecBias);
    360         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, iIntra16Bias);
    361         pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, iInterMBBias);
    362 #endif
    363 
    364     }
    365 
    366     pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_ZERO_THRESH, 0);
    367     *pCount = count;
    368 }
    369 
    370 
    371 static VAStatus pnw__alloc_context_buffer(context_ENC_p ctx, unsigned char is_JPEG)
    372 {
    373     int width, height;
    374     VAStatus vaStatus = VA_STATUS_SUCCESS;
    375 
    376     /* width and height should be source surface's w and h or ?? */
    377     width = ctx->obj_context->picture_width;
    378     height = ctx->obj_context->picture_height;
    379 
    380     if (is_JPEG == 0) {
    381         ctx->pic_params_size  = 256;
    382 
    383         ctx->header_buffer_size = 8 * HEADER_SIZE + MAX_SLICES_PER_PICTURE * HEADER_SIZE;
    384 
    385         ctx->seq_header_ofs = 0;
    386         ctx->pic_header_ofs = HEADER_SIZE;
    387         ctx->eoseq_header_ofs = 2 * HEADER_SIZE;
    388         ctx->eostream_header_ofs = 3 * HEADER_SIZE;
    389         ctx->aud_header_ofs = 4 * HEADER_SIZE;
    390         ctx->sei_buf_prd_ofs = 5 * HEADER_SIZE;
    391         ctx->sei_pic_tm_ofs = 6 * HEADER_SIZE;
    392         ctx->sei_pic_fpa_ofs = 7 * HEADER_SIZE;
    393         ctx->slice_header_ofs = 8 * HEADER_SIZE;
    394         ctx->in_params_ofs = 0;
    395 
    396         ctx->sliceparam_buffer_size = ((sizeof(SLICE_PARAMS) + 15) & 0xfff0) * MAX_SLICES_PER_PICTURE;
    397         /* All frame share same MTX_CURRENT_IN_PARAMS and above/bellow param
    398          * create MTX_CURRENT_IN_PARAMS buffer seperately
    399          * every MB has one MTX_CURRENT_IN_PARAMS structure, and the (N+1) frame can
    400          * reuse (N) frame's structure
    401          */
    402         ctx->in_params_size = ((~0xf) & (15 + 1 + (width + 15) * (height + 15) / (16 * 16))) * sizeof(MTX_CURRENT_IN_PARAMS);
    403         ctx->below_params_size = ((BELOW_PARAMS_SIZE * width * height / (16 * 16)) + 0xf) & (~0xf);
    404         ctx->above_params_size = ((width / 16) * 128 + 15) & (~0xf) ;
    405 
    406         vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->in_params_size, psb_bt_cpu_vpu, &ctx->topaz_in_params_I);
    407         if (VA_STATUS_SUCCESS != vaStatus) {
    408             return vaStatus;
    409         }
    410 
    411         vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->in_params_size, psb_bt_cpu_vpu, &ctx->topaz_in_params_P);
    412         if (VA_STATUS_SUCCESS != vaStatus) {
    413             psb_buffer_destroy(&ctx->topaz_in_params_I);
    414             return vaStatus;
    415         }
    416 
    417         vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->below_params_size * 4, psb_bt_cpu_vpu, &ctx->topaz_below_params);
    418         if (VA_STATUS_SUCCESS != vaStatus) {
    419             psb_buffer_destroy(&ctx->topaz_in_params_P);
    420             psb_buffer_destroy(&ctx->topaz_in_params_I);
    421             return vaStatus;
    422         }
    423 
    424         vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->above_params_size * 4, psb_bt_cpu_vpu, &ctx->topaz_above_params);
    425         if (VA_STATUS_SUCCESS != vaStatus) {
    426             psb_buffer_destroy(&ctx->topaz_in_params_P);
    427             psb_buffer_destroy(&ctx->topaz_in_params_I);
    428             psb_buffer_destroy(&ctx->topaz_below_params);
    429             return vaStatus;
    430         }
    431         ctx->below_params_ofs = 0;
    432         ctx->above_params_ofs = 0;
    433     } else {
    434         /*JPEG encode need three kinds of buffer but doesn't need above/below buffers.*/
    435         ctx->pic_params_size = (sizeof(JPEG_MTX_QUANT_TABLE) + 0xf) & (~0xf);
    436 
    437         ctx->header_buffer_size = (sizeof(JPEG_MTX_DMA_SETUP) + 0xf) & (~0xf);
    438         ctx->sliceparam_buffer_size =  16; /* Not used*/
    439     }
    440     return vaStatus;
    441 }
    442 
    443 unsigned int pnw__get_ipe_control(enum drm_pnw_topaz_codec  eEncodingFormat)
    444 {
    445     unsigned int RegVal = 0;
    446 
    447     RegVal = F_ENCODE(2, MVEA_CR_IPE_GRID_FINE_SEARCH) |
    448              F_ENCODE(0, MVEA_CR_IPE_GRID_SEARCH_SIZE) |
    449              F_ENCODE(1, MVEA_CR_IPE_Y_FINE_SEARCH);
    450 
    451     switch (eEncodingFormat) {
    452     case IMG_CODEC_H263_NO_RC:
    453     case IMG_CODEC_H263_VBR:
    454     case IMG_CODEC_H263_CBR:
    455         RegVal |= F_ENCODE(0, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(0, MVEA_CR_IPE_ENCODING_FORMAT);
    456         break;
    457     case IMG_CODEC_MPEG4_NO_RC:
    458     case IMG_CODEC_MPEG4_VBR:
    459     case IMG_CODEC_MPEG4_CBR:
    460         RegVal |= F_ENCODE(1, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(1, MVEA_CR_IPE_ENCODING_FORMAT);
    461     default:
    462         break;
    463     case IMG_CODEC_H264_NO_RC:
    464     case IMG_CODEC_H264_VBR:
    465     case IMG_CODEC_H264_CBR:
    466     case IMG_CODEC_H264_VCM:
    467         RegVal |= F_ENCODE(2, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(2, MVEA_CR_IPE_ENCODING_FORMAT);
    468         break;
    469     }
    470     RegVal |= F_ENCODE(6, MVEA_CR_IPE_Y_CANDIDATE_NUM);
    471     return RegVal;
    472 }
    473 
    474 
    475 void pnw_DestroyContext(object_context_p obj_context)
    476 {
    477     context_ENC_p ctx;
    478     ctx = (context_ENC_p)obj_context->format_data;
    479 
    480     psb_buffer_destroy(&ctx->topaz_in_params_P);
    481     psb_buffer_destroy(&ctx->topaz_in_params_I);
    482     psb_buffer_destroy(&ctx->topaz_below_params);
    483     psb_buffer_destroy(&ctx->topaz_above_params);
    484 
    485     if (NULL != ctx->slice_param_cache)
    486         free(ctx->slice_param_cache);
    487     if (NULL == ctx->save_seq_header_p)
    488         free(ctx->save_seq_header_p);
    489     free(obj_context->format_data);
    490     obj_context->format_data = NULL;
    491 }
    492 
    493 VAStatus pnw_CreateContext(
    494     object_context_p obj_context,
    495     object_config_p __maybe_unused obj_config,
    496     unsigned char is_JPEG)
    497 {
    498     int width, height;
    499     int i;
    500     unsigned short SearchWidth, SearchHeight, SearchLeftOffset, SearchTopOffset;
    501     context_ENC_p ctx;
    502     VAStatus vaStatus;
    503 
    504     width = obj_context->picture_width;
    505     height = obj_context->picture_height;
    506     ctx = (context_ENC_p) calloc(1, sizeof(struct context_ENC_s));
    507     CHECK_ALLOCATION(ctx);
    508 
    509     obj_context->format_data = (void*) ctx;
    510     ctx->obj_context = obj_context;
    511 
    512     ctx->RawWidth = (unsigned short) width;
    513     ctx->RawHeight = (unsigned short) height;
    514 
    515     if (is_JPEG == 0) {
    516         ctx->Width = (unsigned short)(~0xf & (width + 0xf));
    517         ctx->Height = (unsigned short)(~0xf & (height + 0xf));
    518     } else {
    519         /*JPEG only require them are even*/
    520         ctx->Width = (unsigned short)(~0x1 & (width + 0x1));
    521         ctx->Height = (unsigned short)(~0x1 & (height + 0x1));
    522     }
    523 
    524     /* pre-calculated values based on other stream properties */
    525     SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, ctx->Height);
    526     SearchWidth = min(MVEA_LRB_SEARCH_WIDTH, ctx->Width);
    527     SearchLeftOffset = (((SearchWidth / 2) / 16) * 16);
    528     SearchTopOffset = (((SearchHeight / 2) / 16) * 16);
    529 
    530     ctx->HeightMinus16MinusLRBTopOffset        = ctx->Height - (SearchTopOffset + 16);
    531     ctx->HeightMinus32MinusLRBTopOffset        = ctx->Height - (SearchTopOffset + 32);
    532     ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16     = ctx->Height - (SearchTopOffset + SearchTopOffset + 16);
    533     ctx->HeightMinusLRBSearchHeight    = ctx->Height - SearchHeight;
    534 
    535     ctx->FCode = 0;
    536 
    537     ctx->NumCores = 2; /* FIXME Assume there is two encode cores in Penwell, precise value should read from HW */
    538 
    539     ctx->BelowParamsBufIdx = 0;
    540     ctx->AccessUnitNum = 0;
    541     ctx->SyncSequencer = 0; /* FIXME Refer to DDK */
    542     ctx->SliceToCore =  -1;
    543     ctx->CmdCount = 0xa5a5a5a5 % MAX_TOPAZ_CMD_COUNT;
    544     ctx->FrmIdx = 0;
    545 
    546     for (i = 0; i < MAX_TOPAZ_CORES; i++) {
    547         ctx->LastSliceNum[i] = -1;
    548         ctx->LastSync[0][i] = ~0;
    549         ctx->LastSync[1][i] = ~0;
    550     }
    551 
    552     for (i = 0; i < MAX_SLICES_PER_PICTURE; i++) {
    553         ctx->SliceHeaderReady[i] = IMG_FALSE;
    554     }
    555 
    556     vaStatus = pnw__alloc_context_buffer(ctx, is_JPEG);
    557 
    558     return vaStatus;
    559 }
    560 
    561 VAStatus pnw_BeginPicture(context_ENC_p ctx)
    562 {
    563     VAStatus vaStatus = VA_STATUS_SUCCESS;
    564     pnw_cmdbuf_p cmdbuf;
    565     int ret, i;
    566 
    567     if (ctx->raw_frame_count != 0)
    568         ctx->previous_src_surface = ctx->src_surface;
    569     ctx->src_surface = ctx->obj_context->current_render_target;
    570 
    571     /* clear frameskip flag to 0 */
    572     CLEAR_SURFACE_INFO_skipped_flag(ctx->src_surface->psb_surface);
    573     ctx->none_vcl_nal = 0;
    574 
    575     /*if (ctx->sRCParams.RCEnable == IMG_TRUE)
    576      {
    577      pnw_DetectFrameSkip(ctx);
    578      if (0 != (GET_SURFACE_INFO_skipped_flag(ctx->src_surface->psb_surface)
    579             & SURFACE_INFO_SKIP_FLAG_SETTLED))
    580          ctx->sRCParams.FrameSkip = IMG_TRUE;
    581      else
    582          ctx->sRCParams.FrameSkip = IMG_FALSE;
    583      }*/
    584 
    585     /* Initialise the command buffer */
    586     ret = pnw_context_get_next_cmdbuf(ctx->obj_context);
    587     if (ret) {
    588         drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n");
    589         vaStatus = VA_STATUS_ERROR_UNKNOWN;
    590         return vaStatus;
    591     }
    592     cmdbuf = ctx->obj_context->pnw_cmdbuf;
    593     memset(cmdbuf->cmd_idx_saved, 0, sizeof(cmdbuf->cmd_idx_saved));
    594 
    595 
    596     /* map start_pic param */
    597     vaStatus = psb_buffer_map(&cmdbuf->pic_params, &cmdbuf->pic_params_p);
    598     if (vaStatus) {
    599         return vaStatus;
    600     }
    601     vaStatus = psb_buffer_map(&cmdbuf->header_mem, &cmdbuf->header_mem_p);
    602     if (vaStatus) {
    603         psb_buffer_unmap(&cmdbuf->pic_params);
    604         return vaStatus;
    605     }
    606 
    607     vaStatus = psb_buffer_map(&cmdbuf->slice_params, &cmdbuf->slice_params_p);
    608     if (vaStatus) {
    609         psb_buffer_unmap(&cmdbuf->pic_params);
    610         psb_buffer_unmap(&cmdbuf->header_mem);
    611         return vaStatus;
    612     }
    613 
    614     /* only map topaz param when necessary */
    615     cmdbuf->topaz_above_params_p = NULL;
    616     cmdbuf->topaz_below_params_p = NULL;
    617     cmdbuf->topaz_in_params_I_p = NULL;
    618     cmdbuf->topaz_in_params_P_p = NULL;
    619 
    620     if (ctx->obj_context->frame_count == 0) { /* first picture */
    621 
    622         psb_driver_data_p driver_data = ctx->obj_context->driver_data;
    623 
    624         *cmdbuf->cmd_idx++ = ((MTX_CMDID_SW_NEW_CODEC & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
    625                              (((driver_data->drm_context & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT));
    626         pnw_cmdbuf_insert_command_param(ctx->eCodec);
    627         pnw_cmdbuf_insert_command_param((ctx->Width << 16) | ctx->Height);
    628     }
    629 
    630     ctx->FrmIdx++;
    631     ctx->SliceToCore = ctx->ParallelCores - 1;
    632     /* ctx->AccessUnitNum++;    Move this back to pnw_EndPicture */
    633     ctx->sRCParams.bBitrateChanged = IMG_FALSE;
    634 
    635     for (i = 0; i < MAX_TOPAZ_CORES; i++)
    636         ctx->LastSliceNum[i] = -1;
    637 
    638     for (i = 0; i < MAX_SLICES_PER_PICTURE; i++)
    639         ctx->SliceHeaderReady[i] = IMG_FALSE;
    640 
    641     /*If ParallelCores > 1(H264) and encode one slice per frame, the unnecessary start picture
    642     *commands will be replaced with MTX_CMDID_PAD and ignored by kernel*/
    643     cmdbuf->cmd_idx_saved[PNW_CMDBUF_START_PIC_IDX] = cmdbuf->cmd_idx;
    644 
    645     /* insert START_PIC command for each core */
    646     /* ensure that the master (core #0) will be last to complete this batch */
    647     for (i = (ctx->ParallelCores - 1); i >= 0; i--) {
    648 
    649         /*
    650          * the content of PIC_PARAMS is filled when RenderPicture(...,VAEncPictureParameterBufferXXX)
    651          */
    652         pnw_cmdbuf_insert_command_package(ctx->obj_context,
    653                                           i,
    654                                           MTX_CMDID_START_PIC,
    655                                           &cmdbuf->pic_params,
    656                                           i * ctx->pic_params_size);
    657 
    658         /* no RC paramter provided in vaBeginPicture
    659          * so delay RC param setup into vaRenderPicture(SequenceHeader...)
    660          */
    661     }
    662 
    663     ctx->obj_context->slice_count = 0;
    664     return 0;
    665 }
    666 
    667 
    668 VAStatus pnw_set_bias(context_ENC_p ctx, int core)
    669 {
    670     pnw_cmdbuf_p cmdbuf = (pnw_cmdbuf_p)ctx->obj_context->pnw_cmdbuf;
    671     double flBpp;
    672     IMG_UINT8 THSkip;
    673 
    674     if (ctx->sRCParams.RCEnable) {
    675         flBpp = 1.0 * ctx->sRCParams.BitsPerSecond /
    676                 (ctx->sRCParams.FrameRate * ctx->Width * ctx->Height);
    677     } else {
    678         flBpp =  0.14;
    679     }
    680 
    681     if (flBpp <= 0.07) {
    682         THSkip = TH_SKIP_24;
    683     } else if (flBpp <= 0.14) {
    684         THSkip = TH_SKIP_12;
    685     } else {
    686         THSkip = TH_SKIP_0;
    687     }
    688     switch (ctx->eCodec) {
    689     case IMG_CODEC_H264_VBR:
    690     case IMG_CODEC_H264_CBR:
    691     case IMG_CODEC_H264_VCM:
    692     case IMG_CODEC_H264_NO_RC:
    693         LoadH264Bias(cmdbuf, core, THSkip, ctx->sRCParams.QCPOffset);
    694         break;
    695     case IMG_CODEC_H263_CBR:
    696     case IMG_CODEC_H263_NO_RC:
    697     case IMG_CODEC_H263_VBR:
    698         LoadH263Bias(cmdbuf, core, THSkip);
    699         break;
    700     case IMG_CODEC_MPEG4_NO_RC:
    701     case IMG_CODEC_MPEG4_CBR:
    702     case IMG_CODEC_MPEG4_VBR:
    703         LoadMPEG4Bias(cmdbuf, core, THSkip);
    704         break;
    705     default:
    706         return -1;
    707         break;
    708     }
    709     return 0;
    710 }
    711 
    712 VAStatus pnw_RenderPictureParameter(context_ENC_p ctx, int core)
    713 {
    714     PIC_PARAMS *psPicParams;    /* PIC_PARAMS has been put in pnw_hostcode.h */
    715     object_surface_p src_surface;
    716     unsigned int srf_buf_offset;
    717     object_surface_p rec_surface;
    718     object_surface_p ref_surface;
    719     pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
    720     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
    721 
    722     psPicParams = (PIC_PARAMS *)(cmdbuf->pic_params_p + ctx->pic_params_size * core);
    723 
    724     memset(psPicParams, 0, sizeof(PIC_PARAMS));
    725     /* second frame will reuse some rate control parameters (IN_PARAMS_MP4)
    726      * so only memset picture parames except IN_PARAMS
    727      * BUT now IN_RC_PARAMS was reload from the cache, so it now can
    728      * memset entirE PIC_PARAMS
    729      */
    730 
    731     /*
    732     memset(psPicParams, 0, (int)((unsigned char *)&psPicParams->sInParams - (unsigned char *)psPicParams));
    733     */
    734 
    735     src_surface = ctx->src_surface;
    736     CHECK_SURFACE(src_surface);
    737 
    738     rec_surface = ctx->dest_surface;
    739     CHECK_SURFACE(rec_surface);
    740 
    741     /*The fisrt frame always is I frame and the content of reference frame wouldn't be used.
    742      * But the heights of ref and dest frame should be the same.
    743      * That allows Topaz to keep its motion vectors up to date, which helps maintain performance */
    744     if (ctx->obj_context->frame_count == 0)
    745         ctx->ref_surface = ctx->dest_surface;
    746 
    747     ref_surface = ctx->ref_surface;
    748     CHECK_SURFACE(rec_surface);
    749 
    750     /* clear frameskip flag */
    751     CLEAR_SURFACE_INFO_skipped_flag(rec_surface->psb_surface);
    752     CLEAR_SURFACE_INFO_skipped_flag(ref_surface->psb_surface);
    753 
    754     /* Write video data byte offset into Coded buffer
    755      * If it is here, it will be a SYNC point, which have performance impact
    756      * Move to psb__CreateBuffer
    757      vaStatus = psb_buffer_map(ctx->coded_buf->psb_buffer, &pBuffer);
    758      if(vaStatus) {
    759      DEBUG_FAILURE;
    760      return vaStatus;
    761      }
    762      *(IMG_UINT32 *)(pBuffer+8) = 16;
    763      psb_buffer_unmap(ctx->coded_buf->psb_buffer);
    764     */
    765 
    766     psPicParams->SrcYStride = src_surface->psb_surface->stride;
    767     switch (ctx->eFormat) {
    768     case IMG_CODEC_IYUV:        /* IYUV */
    769     case IMG_CODEC_PL8:
    770         psPicParams->SrcUVStride = src_surface->psb_surface->stride / 2;
    771         psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 8 / 2;
    772         break;
    773     case IMG_CODEC_IMC2:    /* IMC2 */
    774     case IMG_CODEC_PL12:
    775         psPicParams->SrcUVStride = src_surface->psb_surface->stride;
    776         psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 8;
    777         break;
    778     default:
    779         break;
    780     }
    781     psPicParams->SrcYRowStride    = src_surface->psb_surface->stride * 16;
    782     /* psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 16 / 2; */
    783 
    784     /* Dest(rec) stride
    785      * The are now literally Dst stride (not equivalent to 'offset to next row')
    786      */
    787 #ifdef VA_EMULATOR
    788     /* only for simulator, va-emulator needs the actually stride for
    789      * reconstructed frame transfer (va-emulator->driver)
    790      */
    791     psPicParams->DstYStride = rec_surface->psb_surface->stride;
    792     psPicParams->DstUVStride = rec_surface->psb_surface->stride;
    793 #else
    794     psPicParams->DstYStride = rec_surface->psb_surface->stride;
    795     psPicParams->DstUVStride = rec_surface->psb_surface->stride;
    796 #endif
    797 
    798     psPicParams->Width  = ctx->Width;
    799     psPicParams->Height = ctx->Height;
    800     psPicParams->NumSlices = ctx->sRCParams.Slices;
    801 
    802     psPicParams->IsPerSliceOutput = IMG_FALSE;
    803     psPicParams->SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, psPicParams->Height);
    804     psPicParams->SearchWidth = min(MVEA_LRB_SEARCH_WIDTH, psPicParams->Width);
    805 
    806     /* not sure why we are setting this up here... */
    807     psPicParams->Flags = 0;
    808     switch (ctx->eCodec) {
    809     case IMG_CODEC_H264_NO_RC:
    810     case IMG_CODEC_H264_VBR:
    811     case IMG_CODEC_H264_CBR:
    812     case IMG_CODEC_H264_VCM:
    813         psPicParams->Flags |= ISH264_FLAGS;
    814         break;
    815     case IMG_CODEC_H263_VBR:
    816     case IMG_CODEC_H263_CBR:
    817     case IMG_CODEC_H263_NO_RC:
    818         psPicParams->Flags |= ISH263_FLAGS;
    819         break;
    820     case IMG_CODEC_MPEG4_NO_RC:
    821     case IMG_CODEC_MPEG4_VBR:
    822     case IMG_CODEC_MPEG4_CBR:
    823         psPicParams->Flags |= ISMPEG4_FLAGS;
    824         break;
    825     default:
    826         return VA_STATUS_ERROR_UNKNOWN;
    827     }
    828 
    829     switch (ctx->eCodec) {
    830     case IMG_CODEC_H264_VBR:
    831     case IMG_CODEC_MPEG4_VBR:
    832     case IMG_CODEC_H263_VBR:
    833         psPicParams->Flags |= ISVBR_FLAGS;
    834         break;
    835     case IMG_CODEC_H264_VCM:
    836         psPicParams->Flags |= (ISVCM_FLAGS | ISCBR_FLAGS);
    837         break;
    838     case IMG_CODEC_H263_CBR:
    839     case IMG_CODEC_H264_CBR:
    840     case IMG_CODEC_MPEG4_CBR:
    841         psPicParams->Flags |= ISCBR_FLAGS;
    842         break;
    843     case IMG_CODEC_MPEG4_NO_RC:
    844     case IMG_CODEC_H263_NO_RC:
    845     case IMG_CODEC_H264_NO_RC:
    846         break;
    847     default:
    848         return VA_STATUS_ERROR_UNKNOWN;
    849     }
    850 
    851 #if 0
    852     if (ctx->SyncSequencer)
    853         psPicParams->Flags |= SYNC_SEQUENCER;
    854 #endif
    855 
    856     if (ctx->sRCParams.RCEnable) {
    857         if (ctx->sRCParams.bDisableFrameSkipping) {
    858             psPicParams->Flags |= DISABLE_FRAME_SKIPPING;
    859             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Frame skip is disabled.\n");
    860         }
    861 
    862         if (ctx->sRCParams.bDisableBitStuffing && IS_H264_ENC(ctx->eCodec)) {
    863             psPicParams->Flags |= DISABLE_BIT_STUFFING;
    864             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Bit stuffing is disabled.\n");
    865         }
    866 
    867 
    868         /* for the first frame, will setup RC params in EndPicture */
    869         if (ctx->raw_frame_count > 0) { /* reuse in_params parameter */
    870             /* In case, it's changed in a new sequence */
    871             if (ctx->obj_context->frame_count == 0
    872                && ctx->in_params_cache.IntraPeriod != ctx->sRCParams.IntraFreq) {
    873                drv_debug_msg(VIDEO_DEBUG_ERROR,
    874                "On frame %d, Intra period is changed from %d to %d\n",
    875                ctx->raw_frame_count, ctx->in_params_cache.IntraPeriod,
    876                ctx->sRCParams.IntraFreq);
    877                ctx->in_params_cache.IntraPeriod =  ctx->sRCParams.IntraFreq;
    878                ctx->in_params_cache.BitsPerGOP =
    879                     (ctx->sRCParams.BitsPerSecond / ctx->sRCParams.FrameRate)
    880                     * ctx->sRCParams.IntraFreq;
    881             }
    882 
    883             psPicParams->Flags &= ~FIRST_FRAME;
    884             /* reload IN_RC_PARAMS from cache */
    885             memcpy(&psPicParams->sInParams, &ctx->in_params_cache, sizeof(IN_RC_PARAMS));
    886         } else {
    887             psPicParams->Flags |= ISRC_FLAGS;
    888             psPicParams->Flags |= FIRST_FRAME;
    889         }
    890     } else
    891         psPicParams->sInParams.SeInitQP = ctx->sRCParams.InitialQp;
    892 
    893     /* some relocations have to been done here */
    894     srf_buf_offset = src_surface->psb_surface->buf.buffer_ofs;
    895     if (src_surface->psb_surface->buf.type == psb_bt_camera)
    896         drv_debug_msg(VIDEO_DEBUG_GENERAL, "src surface GPU offset 0x%08x, luma offset 0x%08x\n",
    897                                  wsbmBOOffsetHint(src_surface->psb_surface->buf.drm_buf), srf_buf_offset);
    898 
    899     RELOC_PIC_PARAMS_PNW(&psPicParams->SrcYBase, srf_buf_offset, &src_surface->psb_surface->buf);
    900     switch (ctx->eFormat) {
    901     case IMG_CODEC_IYUV:
    902     case IMG_CODEC_PL8:
    903     case IMG_CODEC_PL12:
    904         RELOC_PIC_PARAMS_PNW(&psPicParams->SrcUBase,
    905                              srf_buf_offset + src_surface->psb_surface->chroma_offset,
    906                              &src_surface->psb_surface->buf);
    907 
    908         RELOC_PIC_PARAMS_PNW(&psPicParams->SrcVBase,
    909                              srf_buf_offset + src_surface->psb_surface->chroma_offset * 5 / 4,
    910                              &src_surface->psb_surface->buf);
    911 
    912         break;
    913     case IMG_CODEC_IMC2:
    914     case IMG_CODEC_NV12:
    915     default:
    916         break;
    917     }
    918 
    919     RELOC_PIC_PARAMS_PNW(&psPicParams->DstYBase, 0, &rec_surface->psb_surface->buf);
    920 
    921     RELOC_PIC_PARAMS_PNW(&psPicParams->DstUVBase,
    922                          rec_surface->psb_surface->stride * rec_surface->height,
    923                          &rec_surface->psb_surface->buf);
    924 
    925     RELOC_PIC_PARAMS_PNW(&psPicParams->BelowParamsInBase,
    926                          ctx->below_params_ofs + ctx->below_params_size *(((ctx->AccessUnitNum) & 0x1)),
    927                          cmdbuf->topaz_below_params);
    928 
    929     RELOC_PIC_PARAMS_PNW(&psPicParams->BelowParamsOutBase,
    930                          ctx->below_params_ofs + ctx->below_params_size *(((ctx->AccessUnitNum + 1) & 0x1)),
    931                          cmdbuf->topaz_below_params);
    932 
    933     RELOC_PIC_PARAMS_PNW(&psPicParams->AboveParamsBase,
    934                          ctx->above_params_ofs + ctx->above_params_size *(core * 2 + (ctx->AccessUnitNum & 0x1)),
    935                          cmdbuf->topaz_above_params);
    936 
    937     RELOC_PIC_PARAMS_PNW(&psPicParams->CodedBase, ctx->coded_buf_per_slice * core, ctx->coded_buf->psb_buffer);
    938     drv_debug_msg(VIDEO_DEBUG_GENERAL, "For core %d, above_parmas_off %x\n", core, ctx->above_params_ofs + ctx->above_params_size *(core * 2 + ((ctx->AccessUnitNum) & 0x1)));
    939 
    940    return VA_STATUS_SUCCESS;
    941 }
    942 
    943 static VAStatus pnw_SetupRCParam(context_ENC_p ctx)
    944 {
    945     pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
    946     PIC_PARAMS  *psPicParams = (PIC_PARAMS  *)cmdbuf->pic_params_p;
    947     PIC_PARAMS  *psPicParamsTmp;
    948     int origin_qp, i;/* in DDK setup_rc will change qp strangly,
    949                    * just for keep same with DDK
    950                    */
    951 
    952     origin_qp = ctx->sRCParams.InitialQp;
    953 
    954     psPicParams->Flags |= ISRC_FLAGS;
    955     pnw__setup_rcdata(ctx, psPicParams, &ctx->sRCParams);
    956 
    957     /* restore it, just keep same with DDK */
    958     ctx->sRCParams.InitialQp = origin_qp;
    959 
    960     /* Assume IN_RC_PARAMS for each core is identical, and copy for each */
    961     for (i = (ctx->ParallelCores - 1); i > 0; i--) {
    962         psPicParamsTmp = (PIC_PARAMS  *)(cmdbuf->pic_params_p + ctx->pic_params_size * i);
    963         memcpy((unsigned char *)&psPicParamsTmp->sInParams,
    964                (unsigned char *)&psPicParams->sInParams,
    965                sizeof(IN_RC_PARAMS));
    966         psPicParamsTmp->Flags |= psPicParams->Flags;
    967     }
    968 
    969     /* save IN_RC_PARAMS into the cache */
    970     memcpy(&ctx->in_params_cache, (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
    971     return VA_STATUS_SUCCESS;
    972 }
    973 
    974 VAStatus pnw_EndPicture(context_ENC_p ctx)
    975 {
    976     VAStatus vaStatus = VA_STATUS_SUCCESS;
    977     unsigned int i;
    978     int index;
    979     pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
    980     PIC_PARAMS *psPicParams = (PIC_PARAMS *)cmdbuf->pic_params_p;
    981     PIC_PARAMS *psPicParamsSlave = NULL;
    982     unsigned int val = 0;
    983 
    984     ctx->AccessUnitNum++;
    985 
    986     if (ctx->sRCParams.RCEnable) {
    987         if (ctx->raw_frame_count == 0)
    988             pnw_SetupRCParam(ctx);
    989         else  if (ctx->sRCParams.bBitrateChanged) {
    990             /* Toggle the last bit to make sure encoder firmare recalculate the
    991                RC params even if the target bitrate isn't changed.*/
    992             val = ~(ctx->sRCParams.BitsPerSecond & 0x1);
    993             ctx->sRCParams.BitsPerSecond &= ~1;
    994             ctx->sRCParams.BitsPerSecond |= (val & 1);
    995 
    996             drv_debug_msg(VIDEO_DEBUG_GENERAL, "bitrate is changed to %d, "
    997                     "update the rc data accordingly\n", ctx->sRCParams.BitsPerSecond);
    998             pnw__update_rcdata(ctx, psPicParams, &ctx->sRCParams);
    999             if (ctx->sRCParams.MinQP)
   1000                 psPicParams->sInParams.MinQPVal = ctx->sRCParams.MinQP;
   1001             memcpy(&ctx->in_params_cache, (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
   1002             /* Save rate control info in slave core as well */
   1003             for (i = 1; i < ctx->ParallelCores; i++) {
   1004                 psPicParamsSlave = (PIC_PARAMS *)(cmdbuf->pic_params_p + ctx->pic_params_size * i);
   1005                 memcpy((unsigned char *)&psPicParamsSlave->sInParams,
   1006                         (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
   1007 	    }
   1008         }
   1009     }
   1010 
   1011 #if TOPAZ_PIC_PARAMS_VERBOSE
   1012     drv_debug_msg(VIDEO_DEBUG_GENERAL, "End Picture for frame %d\n", ctx->raw_frame_count);
   1013     drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof PIC_PARAMS %d\n", sizeof(PIC_PARAMS));
   1014     drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof in_params %d\n", sizeof(psPicParams->sInParams));
   1015     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcYBase  0x%08x\n", psPicParams->SrcYBase);
   1016     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcUBase 0x%08x\n", psPicParams->SrcUBase);
   1017     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcVBase 0x%08x\n", psPicParams->SrcVBase);
   1018     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstYBase 0x%08x\n", psPicParams->DstYBase);
   1019     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstUVBase 0x%08x\n", psPicParams->DstUVBase);
   1020     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcYStride 0x%08x\n", psPicParams->SrcYStride);
   1021     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcUVStride 0x%08x\n", psPicParams->SrcUVStride);
   1022     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcYRowStride 0x%08x\n", psPicParams->SrcYRowStride);
   1023     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcUVRowStride 0x%08x\n", psPicParams->SrcUVRowStride);
   1024     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstYStride 0x%08x\n", psPicParams->DstYStride);
   1025     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstUVStride 0x%08x\n", psPicParams->DstUVStride);
   1026     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->CodedBase 0x%08x\n", psPicParams->CodedBase);
   1027     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->BelowParamsInBase 0x%08x\n", psPicParams->BelowParamsInBase);
   1028     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->BelowParamsOutBase 0x%08x\n", psPicParams->BelowParamsOutBase);
   1029     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->AboveParamsBase 0x%08x\n", psPicParams->AboveParamsBase);
   1030     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->Width 0x%08x\n", psPicParams->Width);
   1031     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->Height 0x%08x\n", psPicParams->Height);
   1032     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->Flags 0x%08x\n", psPicParams->Flags);
   1033     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SerachWidth 0x%08x\n", psPicParams->SearchWidth);
   1034     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SearchHeight 0x%08x\n", psPicParams->SearchHeight);
   1035     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->NumSlices 0x%08x\n", psPicParams->NumSlices);
   1036     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->ClockDivBitrate %lld\n", psPicParams->ClockDivBitrate);
   1037     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->MaxBufferMultClockDivBitrate %d\n",
   1038                              psPicParams->MaxBufferMultClockDivBitrate);
   1039     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.SeInitQP %d\n", psPicParams->sInParams.SeInitQP);
   1040     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MinQPVal %d\n", psPicParams->sInParams.MinQPVal);
   1041     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MaxQPVal %d\n", psPicParams->sInParams.MaxQPVal);
   1042     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MBPerRow %d\n", psPicParams->sInParams.MBPerRow);
   1043     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MBPerFrm %d\n", psPicParams->sInParams.MBPerFrm);
   1044     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MBPerBU %d\n", psPicParams->sInParams.MBPerBU);
   1045     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BUPerFrm %d\n", psPicParams->sInParams.BUPerFrm);
   1046     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.IntraPeriod %d\n", psPicParams->sInParams.IntraPeriod);
   1047     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerFrm %d\n", psPicParams->sInParams.BitsPerFrm);
   1048     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerBU %d\n", psPicParams->sInParams.BitsPerBU);
   1049     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerMB %d\n", psPicParams->sInParams.BitsPerMB);
   1050     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitRate %d\n", psPicParams->sInParams.BitRate);
   1051     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BufferSize %d\n", psPicParams->sInParams.BufferSize);
   1052     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.InitialLevel %d\n", psPicParams->sInParams.InitialLevel);
   1053     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.InitialDelay %d\n", psPicParams->sInParams.InitialDelay);
   1054     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.ScaleFactor %d\n", psPicParams->sInParams.ScaleFactor);
   1055     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.VCMBitrateMargin %d\n", psPicParams->sInParams.VCMBitrateMargin);
   1056     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.HalfFrameRate %d\n", psPicParams->sInParams.HalfFrameRate);
   1057     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.FCode %d\n", psPicParams->sInParams.FCode);
   1058     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerGOP %d\n", psPicParams->sInParams.BitsPerGOP);
   1059     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.AvQPVal %d\n", psPicParams->sInParams.AvQPVal);
   1060     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MyInitQP %d\n", psPicParams->sInParams.MyInitQP);
   1061     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.ForeceSkipMargin %d\n", psPicParams->sInParams.ForeceSkipMargin);
   1062     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.RCScaleFactor %d\n", psPicParams->sInParams.RCScaleFactor);
   1063     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.TransferRate %d\n", psPicParams->sInParams.TransferRate);
   1064     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MaxFrameSize %d\n", psPicParams->sInParams.MaxFrameSize);
   1065 #endif
   1066     /* save current settings */
   1067     ctx->previous_ref_surface = ctx->ref_surface;
   1068     ctx->previous_dest_surface = ctx->dest_surface; /* reconstructed surface */
   1069     SET_CODEDBUF_INFO(SLICE_NUM, ctx->coded_buf->codedbuf_aux_info,
   1070         ctx->obj_context->slice_count);
   1071     SET_CODEDBUF_INFO(NONE_VCL_NUM, ctx->coded_buf->codedbuf_aux_info,
   1072         ctx->none_vcl_nal);
   1073 
   1074     for (index = (ctx->ParallelCores - 1); index >= 0; index--) {
   1075         pnw_cmdbuf_insert_command_package(ctx->obj_context,
   1076                                           index,
   1077                                           MTX_CMDID_END_PIC,
   1078                                           NULL,
   1079                                           0);
   1080     }
   1081     psb_buffer_unmap(&cmdbuf->pic_params);
   1082     psb_buffer_unmap(&cmdbuf->header_mem);
   1083     psb_buffer_unmap(&cmdbuf->slice_params);
   1084 
   1085     /* unmap MTX_CURRENT_IN_PARAMS buffer only when it is mapped */
   1086     if (cmdbuf->topaz_in_params_I_p != NULL) {
   1087         psb_buffer_unmap(cmdbuf->topaz_in_params_I);
   1088         cmdbuf->topaz_in_params_I_p = NULL;
   1089     }
   1090 
   1091     if (cmdbuf->topaz_in_params_P_p != NULL) {
   1092         psb_buffer_unmap(cmdbuf->topaz_in_params_P);
   1093         cmdbuf->topaz_in_params_P_p = NULL;
   1094     }
   1095 
   1096     if (cmdbuf->topaz_above_params_p != NULL) {
   1097         psb_buffer_unmap(cmdbuf->topaz_above_params);
   1098         cmdbuf->topaz_above_params_p = NULL;
   1099     }
   1100 
   1101     if (cmdbuf->topaz_below_params_p != NULL) {
   1102         psb_buffer_unmap(cmdbuf->topaz_below_params);
   1103         cmdbuf->topaz_below_params_p = NULL;
   1104     }
   1105 
   1106     if (pnw_context_flush_cmdbuf(ctx->obj_context)) {
   1107         vaStatus = VA_STATUS_ERROR_UNKNOWN;
   1108     }
   1109     ctx->raw_frame_count++;
   1110     return vaStatus;
   1111 }
   1112 
   1113 static void pnw__setup_busize(context_ENC_p ctx)
   1114 {
   1115     unsigned int old_busize = ctx->sRCParams.BUSize;
   1116     int slices = ctx->obj_context->slice_count;
   1117 
   1118     /* it is called at EndPicture, we should now the Slice number */
   1119     //ctx->Slices = ctx->obj_context->slice_count;
   1120 
   1121     /* if no BU size is given then pick one ourselves */
   1122     if (ctx->sRCParams.BUSize != 0)  { /* application provided BUSize */
   1123         IMG_UINT32 MBs, MBsperSlice, MBsLastSlice;
   1124         IMG_UINT32 BUs;
   1125         IMG_INT32  SliceHeight;
   1126         IMG_UINT32 MaxSlicesPerPipe, MaxMBsPerPipe, MaxBUsPerPipe;
   1127 
   1128         MBs     = ctx->Height * ctx->Width / (16 * 16);
   1129 
   1130         SliceHeight     = ctx->Height / slices;
   1131         /* SliceHeight += 15; */
   1132         SliceHeight &= ~15;
   1133 
   1134         MBsperSlice     = (SliceHeight * ctx->Width) / (16 * 16);
   1135         MBsLastSlice    = MBs - (MBsperSlice * (slices - 1));
   1136 
   1137         /* they have given us a basic unit so validate it */
   1138         if (ctx->sRCParams.BUSize < 6) {
   1139             drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too small, must be greater than 6\n");
   1140             ctx->sRCParams.BUSize = 0; /* need repatch */;
   1141         }
   1142         if (ctx->sRCParams.BUSize > MBsperSlice) {
   1143             drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too large, must be less than the number of macroblocks in a slice\n");
   1144             ctx->sRCParams.BUSize = 0; /* need repatch */;
   1145         }
   1146         if (ctx->sRCParams.BUSize > MBsLastSlice) {
   1147             drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too large, must be less than number of macroblocks in the last slice\n");
   1148             ctx->sRCParams.BUSize = 0; /* need repatch */;
   1149         }
   1150 
   1151         if (ctx->sRCParams.BUSize != 0) {
   1152             BUs = MBsperSlice / ctx->sRCParams.BUSize;
   1153             if ((BUs * ctx->sRCParams.BUSize) != MBsperSlice)   {
   1154                 drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size not an integer divisor of MB's in a slice");
   1155                 ctx->sRCParams.BUSize = 0; /* need repatch */;
   1156             }
   1157         }
   1158         if (ctx->sRCParams.BUSize != 0) {
   1159             BUs = MBsLastSlice / ctx->sRCParams.BUSize;
   1160             if ((BUs * ctx->sRCParams.BUSize) != MBsLastSlice)   {
   1161                 drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size not an integer divisor of MB's in a slice");
   1162                 ctx->sRCParams.BUSize = 0; /* need repatch */;
   1163             }
   1164         }
   1165 
   1166         if (ctx->sRCParams.BUSize != 0) {
   1167             // check if the number of BUs per pipe is greater than 200
   1168             MaxSlicesPerPipe = (slices + ctx->ParallelCores - 1) / ctx->ParallelCores;
   1169             MaxMBsPerPipe = (MBsperSlice * (MaxSlicesPerPipe - 1)) + MBsLastSlice;
   1170             MaxBUsPerPipe = (MaxMBsPerPipe + ctx->sRCParams.BUSize - 1) / ctx->sRCParams.BUSize;
   1171             if (MaxBUsPerPipe > 200) {
   1172                 drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too small. There must be less than 200 basic units per slice");
   1173                 ctx->sRCParams.BUSize = 0; /* need repatch */;
   1174             }
   1175         }
   1176     }
   1177 
   1178     if (ctx->sRCParams.BUSize == 0)  {
   1179         IMG_UINT32 MBs, MBsperSlice, MBsLastSlice;
   1180         IMG_UINT32 BUsperSlice, BUsLastSlice;
   1181         IMG_UINT32 MaxSlicesPerPipe, MaxMBsPerPipe, MaxBUsPerPipe;
   1182         IMG_INT32  SliceHeight;
   1183         IMG_UINT32 BUSize = 6;
   1184 
   1185         MBs     = ctx->Height * ctx->Width / (16 * 16);
   1186 
   1187         SliceHeight     = ctx->Height / slices;
   1188         /* SliceHeight += 15; */
   1189         SliceHeight &= ~15;
   1190 
   1191         MBsperSlice     = (SliceHeight * ctx->Width) / (16 * 16);
   1192         MBsLastSlice = MBs - (MBsperSlice * (slices - 1));
   1193 
   1194         /* Check number of BUs to be encoded on one pipe is less than maximum number allowed 200  */
   1195         MaxSlicesPerPipe = (slices + ctx->ParallelCores - 1) / ctx->ParallelCores;
   1196         MaxMBsPerPipe = (MBsperSlice * (MaxSlicesPerPipe - 1)) + MBsLastSlice;
   1197         MaxBUsPerPipe = (MaxMBsPerPipe + BUSize - 1) / BUSize;
   1198 
   1199         while (MaxBUsPerPipe > 200)  {
   1200             BUSize++;
   1201             MaxBUsPerPipe = (MaxMBsPerPipe + BUSize - 1) / BUSize;
   1202         }
   1203 
   1204         /* Check whether there are integeral number of BUs in the slices  */
   1205         BUsperSlice = MBsperSlice / BUSize;
   1206         BUsLastSlice = MBsLastSlice / BUSize;
   1207         while ((BUsperSlice*BUSize != MBsperSlice) ||
   1208                (BUsLastSlice*BUSize != MBsLastSlice)) {
   1209             BUSize++;
   1210             BUsperSlice = MBsperSlice / BUSize;
   1211             BUsLastSlice = MBsLastSlice / BUSize;
   1212         }
   1213 
   1214         ctx->sRCParams.BUSize = BUSize;
   1215     /*
   1216         ctx->sRCParams.InitialLevel = (3 * ctx->sRCParams.BufferSize) >> 4;
   1217         ctx->sRCParams.InitialDelay = (13 * ctx->sRCParams.BufferSize) >> 4;
   1218     */
   1219     }
   1220 
   1221     if (ctx->sRCParams.BUSize != old_busize)
   1222         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Patched Basic unit to %d (original=%d)\n", ctx->sRCParams.BUSize, old_busize);
   1223 }
   1224 
   1225 
   1226 static void pnw__update_rcdata(
   1227     context_ENC_p psContext,
   1228     PIC_PARAMS *psPicParams,
   1229     IMG_RC_PARAMS *psRCParams)
   1230 {
   1231     double      L1, L2, L3, L4, L5, L6, flBpp;
   1232     IMG_INT16           i16TempQP;
   1233     IMG_INT32   i32BufferSizeInFrames = 0;
   1234 
   1235     flBpp = 1.0 * psRCParams->BitsPerSecond
   1236             / (psRCParams->FrameRate * psContext->Width * psContext->Height);
   1237 
   1238     if (psContext->Width <= 176) {
   1239         /* for very small franes we need to adjust the calculations */
   1240         flBpp = flBpp / 2.0;
   1241     }
   1242 
   1243     psPicParams->sInParams.IntraPeriod =  psRCParams->IntraFreq;
   1244     psPicParams->sInParams.BitRate = psRCParams->BitsPerSecond;
   1245     psPicParams->sInParams.BitsPerFrm = (psRCParams->BitsPerSecond + psRCParams->FrameRate / 2) / psRCParams->FrameRate;
   1246     psPicParams->sInParams.BitsPerGOP = (psRCParams->BitsPerSecond / psRCParams->FrameRate) * psRCParams->IntraFreq;
   1247     psPicParams->sInParams.BitsPerBU    = psPicParams->sInParams.BitsPerFrm / (4 * psPicParams->sInParams.BUPerFrm);
   1248     psPicParams->sInParams.BitsPerMB    = psPicParams->sInParams.BitsPerBU / psRCParams->BUSize;
   1249     psPicParams->sInParams.TransferRate = psRCParams->BitsPerSecond / psRCParams->FrameRate;
   1250 
   1251     i32BufferSizeInFrames = psRCParams->BufferSize / psPicParams->sInParams.BitsPerFrm;
   1252 
   1253     /* select thresholds and initial Qps etc that are codec dependent */
   1254     switch (psContext->eCodec) {
   1255     case IMG_CODEC_H264_CBR:
   1256     case IMG_CODEC_H264_VCM:
   1257     case IMG_CODEC_H264_VBR:
   1258         L1 = 0.1;
   1259         L2 = 0.15;
   1260         L3 = 0.2;
   1261 
   1262         /* Set MaxQP to avoid blocky image in low bitrate */
   1263         /* RCScaleFactor indicates the size of GOP for rate control */
   1264         if (psContext->eCodec == IMG_CODEC_H264_VCM) {
   1265             psPicParams->sInParams.MaxQPVal = 51;
   1266             psPicParams->sInParams.RCScaleFactor = 16;
   1267         }
   1268         else {
   1269             psPicParams->sInParams.MaxQPVal = 51;
   1270             psPicParams->sInParams.RCScaleFactor = 16;
   1271         }
   1272 
   1273         /* Setup MAX and MIN Quant Values */
   1274         if (flBpp >= 0.50)
   1275             i16TempQP = 4;
   1276         else
   1277             i16TempQP = (unsigned int)(26 - (40 * flBpp));
   1278 
   1279         psPicParams->sInParams.MinQPVal = (max(min(psPicParams->sInParams.MaxQPVal, i16TempQP), 0));
   1280 
   1281         L1 = 0.050568;
   1282         L2 = 0.202272;
   1283         L3 = 0.40454321;
   1284         L4 = 0.80908642;
   1285         L5 = 1.011358025;
   1286         if (flBpp < L1)
   1287             psPicParams->sInParams.SeInitQP = (IMG_UINT8)(47 - 78.10 * flBpp);
   1288 
   1289         else if (flBpp >= L1 && flBpp < L2)
   1290             psPicParams->sInParams.SeInitQP = (IMG_UINT8)(45 - 66.67 * flBpp);
   1291 
   1292         else if (flBpp >= L2 && flBpp < L3)
   1293             psPicParams->sInParams.SeInitQP = (IMG_UINT8)(36 - 24.72 * flBpp);
   1294 
   1295         else if (flBpp >= L3 && flBpp < L4)
   1296             psPicParams->sInParams.SeInitQP = (IMG_UINT8)(34 - 19.78 * flBpp);
   1297 
   1298         else if (flBpp >= L4 && flBpp < L5)
   1299             psPicParams->sInParams.SeInitQP = (IMG_UINT8)(27 - 9.89 * flBpp);
   1300 
   1301         else if (flBpp >= L5 && flBpp < 4)
   1302             psPicParams->sInParams.SeInitQP = (IMG_UINT8)(20 - 4.95 * flBpp);
   1303         else
   1304             psPicParams->sInParams.SeInitQP = psPicParams->sInParams.MinQPVal;
   1305 
   1306         if (psPicParams->sInParams.SeInitQP < psPicParams->sInParams.MinQPVal)
   1307             psPicParams->sInParams.SeInitQP = psPicParams->sInParams.MinQPVal;
   1308 
   1309         break;
   1310 
   1311     case IMG_CODEC_MPEG4_CBR:
   1312     case IMG_CODEC_MPEG4_VBR:
   1313     case IMG_CODEC_H263_CBR:
   1314     case IMG_CODEC_H263_VBR:
   1315         psPicParams->sInParams.RCScaleFactor = 16;
   1316         psPicParams->sInParams.MaxQPVal  = 31;
   1317 
   1318         if (psContext->Width <= 176) {
   1319             L1 = 0.043;
   1320             L2 = 0.085;
   1321             L3 = 0.126;
   1322             L4 = 0.168;
   1323             L5 = 0.336;
   1324             L6 = 0.505;
   1325         } else if (psContext->Width == 352) {
   1326             L1 = 0.065;
   1327             L2 = 0.085;
   1328             L3 = 0.106;
   1329             L4 = 0.126;
   1330             L5 = 0.168 ;
   1331             L6 = 0.210;
   1332         } else {
   1333             L1 = 0.051;
   1334             L2 = 0.0770;
   1335             L3 = 0.096;
   1336             L4 = 0.145;
   1337             L5 = 0.193;
   1338             L6 = 0.289;
   1339         }
   1340 
   1341         /* Calculate Initial QP if it has not been specified */
   1342         if (flBpp < L1)
   1343             psPicParams->sInParams.SeInitQP = 31;
   1344 
   1345         else if (flBpp >= L1 && flBpp < L2)
   1346             psPicParams->sInParams.SeInitQP = 26;
   1347 
   1348         else if (flBpp >= L2 && flBpp < L3)
   1349             psPicParams->sInParams.SeInitQP = 22;
   1350 
   1351         else if (flBpp >= L3 && flBpp < L4)
   1352             psPicParams->sInParams.SeInitQP = 18;
   1353 
   1354         else if (flBpp >= L4 && flBpp < L5)
   1355             psPicParams->sInParams.SeInitQP = 14;
   1356 
   1357         else if (flBpp >= L5 && flBpp < L6)
   1358             psPicParams->sInParams.SeInitQP = 10;
   1359         else
   1360             psPicParams->sInParams.SeInitQP = 8;
   1361 
   1362         psPicParams->sInParams.AvQPVal =  psPicParams->sInParams.SeInitQP;
   1363 
   1364         if (flBpp >= 0.25
   1365                 && (psContext->eCodec == IMG_CODEC_MPEG4_CBR ||
   1366                     psContext->eCodec == IMG_CODEC_MPEG4_VBR)) {
   1367             psPicParams->sInParams.MinQPVal = 1;
   1368         } else {
   1369             psPicParams->sInParams.MinQPVal = 4;
   1370         }
   1371         break;
   1372 
   1373     default:
   1374         /* the NO RC cases will fall here */
   1375         break;
   1376     }
   1377 
   1378     /* Set up Input Parameters that are mode dependent */
   1379     switch (psContext->eCodec) {
   1380     case IMG_CODEC_H264_NO_RC:
   1381     case IMG_CODEC_H263_NO_RC:
   1382     case IMG_CODEC_MPEG4_NO_RC:
   1383         return ;
   1384 
   1385     case IMG_CODEC_H264_VCM:
   1386         psPicParams->Flags      |= (ISVCM_FLAGS | ISCBR_FLAGS);
   1387         if (psContext->Height >= 480) {
   1388             /* for SD and above we can target 95% (122/128) of maximum bitrate */
   1389             psPicParams->sInParams.VCMBitrateMargin = 122;
   1390         } else {
   1391             /* for less and SD we target 99% of maximum bitrate */
   1392             psPicParams->sInParams.VCMBitrateMargin = 127;
   1393         }
   1394         if (i32BufferSizeInFrames < 15) {
   1395             /* when we have a very small window size we reduce the target
   1396              * further to avoid too much skipping */
   1397             psPicParams->sInParams.VCMBitrateMargin -= 5;
   1398         }
   1399         psPicParams->sInParams.ForeceSkipMargin = 0; /* start skipping MBs when within 500 bits of slice or frame limit */
   1400         if (psRCParams->BitsPerSecond < 1000000) {      // 1 Mbits/s
   1401             psPicParams->sInParams.ScaleFactor = 0;
   1402         } else if (psRCParams->BitsPerSecond < 2000000) { // 2 Mbits/s
   1403             psPicParams->sInParams.ScaleFactor = 1;
   1404         } else if (psRCParams->BitsPerSecond < 4000000) { // 4 Mbits/s
   1405             psPicParams->sInParams.ScaleFactor = 2;
   1406         } else if (psRCParams->BitsPerSecond < 8000000) { // 8 Mbits/s
   1407             psPicParams->sInParams.ScaleFactor = 3;
   1408         } else {
   1409             psPicParams->sInParams.ScaleFactor = 4;
   1410         }
   1411 
   1412         psPicParams->sInParams.BufferSize = i32BufferSizeInFrames;
   1413 
   1414         break;
   1415     case IMG_CODEC_H264_CBR:
   1416         psPicParams->Flags |= ISCBR_FLAGS;
   1417         /* ------------------- H264 CBR RC ------------------- */
   1418         /* Initialize the parameters of fluid flow traffic model. */
   1419         psPicParams->sInParams.BufferSize = psRCParams->BufferSize;
   1420 
   1421         /* HRD consideration - These values are used by H.264 reference code. */
   1422         if (psRCParams->BitsPerSecond < 1000000) {      /* 1 Mbits/s */
   1423             psPicParams->sInParams.ScaleFactor = 0;
   1424         } else if (psRCParams->BitsPerSecond < 2000000) { /* 2 Mbits/s */
   1425             psPicParams->sInParams.ScaleFactor = 1;
   1426         } else if (psRCParams->BitsPerSecond < 4000000) { /* 4 Mbits/s */
   1427             psPicParams->sInParams.ScaleFactor = 2;
   1428         } else if (psRCParams->BitsPerSecond < 8000000) { /* 8 Mbits/s */
   1429             psPicParams->sInParams.ScaleFactor = 3;
   1430         } else {
   1431             psPicParams->sInParams.ScaleFactor = 4;
   1432         }
   1433         break;
   1434 
   1435     case IMG_CODEC_MPEG4_CBR:
   1436     case IMG_CODEC_H263_CBR:
   1437         psPicParams->Flags |= ISCBR_FLAGS;
   1438 
   1439         flBpp  = 256 * (psRCParams->BitsPerSecond / psContext->Width);
   1440         flBpp /= (psContext->Height * psRCParams->FrameRate);
   1441 
   1442         if ((psPicParams->sInParams.MBPerFrm > 1024 && flBpp < 16) || (psPicParams->sInParams.MBPerFrm <= 1024 && flBpp < 24))
   1443             psPicParams->sInParams.HalfFrameRate = 1;
   1444         else
   1445             psPicParams->sInParams.HalfFrameRate = 0;
   1446 
   1447         if (psPicParams->sInParams.HalfFrameRate >= 1) {
   1448             psPicParams->sInParams.SeInitQP = 31;
   1449             psPicParams->sInParams.AvQPVal = 31;
   1450             psPicParams->sInParams.MyInitQP = 31;
   1451         }
   1452 
   1453         psPicParams->sInParams.BufferSize = psRCParams->BufferSize;
   1454         if (psPicParams->sInParams.BufferSize > 112 * 16384) // Simple Profile L5 Constraints
   1455             psPicParams->sInParams.BufferSize = 112 * 16384;
   1456         break;
   1457 
   1458     case IMG_CODEC_MPEG4_VBR:
   1459     case IMG_CODEC_H263_VBR:
   1460     case IMG_CODEC_H264_VBR:
   1461         psPicParams->Flags |= ISVBR_FLAGS;
   1462 
   1463         psPicParams->sInParams.MBPerBU  = psPicParams->sInParams.MBPerFrm;
   1464         psPicParams->sInParams.BUPerFrm = 1;
   1465 
   1466         /* Initialize the parameters of fluid flow traffic model. */
   1467         psPicParams->sInParams.BufferSize = psRCParams->BufferSize;
   1468 
   1469         if (psContext->eCodec != IMG_CODEC_H264_VBR) {
   1470             if (psPicParams->sInParams.BufferSize >  112 * 16384)
   1471                 psPicParams->sInParams.BufferSize = 112 * 16384; // Simple Profile L5 Constraints
   1472         }
   1473 
   1474         /* These scale factor are used only for rate control to avoid overflow */
   1475         /* in fixed-point calculation these scale factors are decided by bit rate */
   1476         if (psRCParams->BitsPerSecond < 640000) {
   1477             psPicParams->sInParams.ScaleFactor  = 2;                                            /* related to complexity */
   1478         } else if (psRCParams->BitsPerSecond < 2000000) {
   1479             psPicParams->sInParams.ScaleFactor  = 4;
   1480         } else {
   1481             psPicParams->sInParams.ScaleFactor  = 6;
   1482         }
   1483         break;
   1484     default:
   1485         break;
   1486     }
   1487 
   1488     psPicParams->sInParams.MyInitQP     = psPicParams->sInParams.SeInitQP;
   1489 
   1490 #if 0
   1491     if (psContext->SyncSequencer)
   1492         psPicParams->Flags |= SYNC_SEQUENCER;
   1493 #endif
   1494 
   1495     psPicParams->sInParams.InitialDelay = psRCParams->InitialDelay;
   1496     psPicParams->sInParams.InitialLevel = psRCParams->InitialLevel;
   1497     psRCParams->InitialQp = psPicParams->sInParams.SeInitQP;
   1498 
   1499     drv_debug_msg(VIDEO_DEBUG_GENERAL, "InitQP %d, minQP %d, maxQP %d\n",
   1500             psPicParams->sInParams.SeInitQP,
   1501             psPicParams->sInParams.MinQPVal,
   1502             psPicParams->sInParams.MaxQPVal);
   1503 
   1504     /* The rate control uses this value to adjust the reaction rate
   1505        to larger than expected frames in long GOPS*/
   1506 
   1507     return;
   1508 }
   1509 
   1510 
   1511 /***********************************************************************************
   1512  * Function Name      : SetupRCData
   1513  * Inputs             :
   1514  * Outputs            :
   1515  * Returns            :
   1516  * Description        : Sets up RC Data
   1517  ************************************************************************************/
   1518 void pnw__setup_rcdata(
   1519     context_ENC_p psContext,
   1520     PIC_PARAMS *psPicParams,
   1521     IMG_RC_PARAMS *psRCParams)
   1522 {
   1523     IMG_UINT8   ui8InitialSeInitQP;
   1524 
   1525     /* frameskip is always cleared, specially handled at vaEndPicture */
   1526     psRCParams->FrameSkip = 0;
   1527 
   1528     if (!psRCParams->BitsPerSecond)
   1529         psRCParams->BitsPerSecond = 64000;
   1530     /*
   1531         if (psRCParams->BitsPerSecond > max_bitrate)
   1532             psRCParams->BitsPerSecond = max_bitrate;
   1533     */
   1534     if (!psRCParams->FrameRate)
   1535         psRCParams->FrameRate = 30;
   1536 
   1537     pnw__setup_busize(psContext); /* calculate BasicUnitSize */
   1538 
   1539     psPicParams->sInParams.SeInitQP = psRCParams->InitialQp;
   1540 
   1541     psPicParams->sInParams.MBPerRow = (psContext->Width >> 4);
   1542     psPicParams->sInParams.MBPerBU = psRCParams->BUSize;
   1543     psPicParams->sInParams.MBPerFrm     = (psContext->Width >> 4) * (psContext->Height >> 4);
   1544     psPicParams->sInParams.BUPerFrm     = (psPicParams->sInParams.MBPerFrm) / psRCParams->BUSize;
   1545     psPicParams->sInParams.AvQPVal = psRCParams->InitialQp;
   1546     psPicParams->sInParams.MyInitQP     = psRCParams->InitialQp;
   1547     psPicParams->sInParams.MaxFrameSize = psRCParams->BitsPerSecond / psRCParams->FrameRate;
   1548 
   1549     ui8InitialSeInitQP = psPicParams->sInParams.SeInitQP;
   1550 
   1551     pnw__update_rcdata(psContext, psPicParams, psRCParams);
   1552 
   1553     /*If MinQP has been set, restore this value rather than
   1554      *the calculated value set by UpdateRCData()*/
   1555     if (psRCParams->MinQP) {
   1556         psPicParams->sInParams.MinQPVal = (IMG_UINT8)psRCParams->MinQP;
   1557     }
   1558 
   1559     /*If SeInitQP has been set, restore this value and other
   1560      * dependant variables rather than the calculated values set by UpdateRCData()*/
   1561     if (ui8InitialSeInitQP) {
   1562         psPicParams->sInParams.SeInitQP = ui8InitialSeInitQP;
   1563         psPicParams->sInParams.MyInitQP = ui8InitialSeInitQP;
   1564         psRCParams->InitialQp = ui8InitialSeInitQP;
   1565     }
   1566 
   1567     /* HRD parameters are meaningless without a bitrate
   1568      * HRD parameters are not supported in VCM mode */
   1569     if (psRCParams->BitsPerSecond == 0 || psContext->eCodec == IMG_CODEC_H264_VCM)
   1570          psContext->bInserHRDParams = IMG_FALSE;
   1571 
   1572     if (psContext->bInserHRDParams) {
   1573         psPicParams->ClockDivBitrate = (90000 * 0x100000000LL);
   1574         psPicParams->ClockDivBitrate /= psRCParams->BitsPerSecond;
   1575         psPicParams->MaxBufferMultClockDivBitrate = (IMG_UINT32)
   1576                 (((IMG_UINT64)(psRCParams->BufferSize) * (IMG_UINT64) 90000)
   1577                  / (IMG_UINT64) psRCParams->BitsPerSecond);
   1578     }
   1579     return ;
   1580 }
   1581 
   1582 static void pnw__setup_qpvalue_h264(
   1583     MTX_CURRENT_IN_PARAMS * psCurrent,
   1584     IMG_BYTE bySliceQP)
   1585 {
   1586     /* H.264 QP scaling tables */
   1587     IMG_BYTE HOST_PVR_QP_SCALE_CR[52] = {
   1588         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
   1589         12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
   1590         28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36, 37, 37,
   1591         37, 38, 38, 38, 39, 39, 39, 39
   1592     };
   1593 
   1594     psCurrent->bySliceQP = bySliceQP;
   1595     psCurrent->bySliceQPC = HOST_PVR_QP_SCALE_CR[psCurrent->bySliceQP];
   1596 }
   1597 
   1598 
   1599 static void pnw__setup_qpvalues_mpeg4(
   1600     MTX_CURRENT_IN_PARAMS * psCurrent,
   1601     IMG_BYTE bySliceQP)
   1602 {
   1603     psCurrent->bySliceQP =      bySliceQP;
   1604 }
   1605 
   1606 static void pnw__setup_slice_row_params(
   1607     context_ENC_p ctx,
   1608     IMG_BOOL IsIntra,
   1609     IMG_UINT16 CurrentRowY,
   1610     IMG_INT16 SliceStartRowY,
   1611     IMG_INT16 SliceHeight,
   1612     IMG_BOOL VectorsValid,
   1613     int bySliceQP)
   1614 {
   1615     /* Note: CurrentRowY and SliceStartRowY are now in pixels (not MacroBlocks)
   1616      * - saves needless multiplications and divisions
   1617      */
   1618     MTX_CURRENT_IN_PARAMS *psCurrent;
   1619     pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
   1620 
   1621     IMG_INT16   iPos, iYPos, srcY;
   1622     IMG_UINT16  ui16tmp;
   1623     IMG_UINT16 ui16SearchWidth, ui16SearchHeight, ui16SearchLeftOffset, ui16SearchTopOffset, ui16CurBlockX;
   1624 
   1625     if (IsIntra && cmdbuf->topaz_in_params_I_p == NULL) {
   1626         VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_in_params_I, &cmdbuf->topaz_in_params_I_p);
   1627         if (vaStatus != VA_STATUS_SUCCESS) {
   1628             drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
   1629             return;
   1630         }
   1631     }
   1632 
   1633     if ((!IsIntra) && cmdbuf->topaz_in_params_P_p == NULL) {
   1634         VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_in_params_P, &cmdbuf->topaz_in_params_P_p);
   1635         if (vaStatus != VA_STATUS_SUCCESS) {
   1636             drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
   1637             return;
   1638         }
   1639     }
   1640 
   1641     if (IsIntra)
   1642         psCurrent = (MTX_CURRENT_IN_PARAMS*)(cmdbuf->topaz_in_params_I_p + ctx->in_params_ofs);
   1643     else
   1644         psCurrent = (MTX_CURRENT_IN_PARAMS*)(cmdbuf->topaz_in_params_P_p + ctx->in_params_ofs);
   1645 
   1646     psCurrent += (CurrentRowY  * (ctx->Width) / 256);
   1647 
   1648     // Note: CurrentRowY and iSliceStartRowY are now in pixels (not MacroBlocks) - saves needless multiplications and divisions
   1649 
   1650     ui16SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, ctx->Height);
   1651     ui16SearchWidth = min(MVEA_LRB_SEARCH_WIDTH, ctx->Width);
   1652     ui16SearchLeftOffset = (((ui16SearchWidth / 2) / 16) * 16); // this is the amount of data that gets preloaded
   1653     ui16SearchTopOffset = (((ui16SearchHeight / 2) / 16) * 16);
   1654     ui16CurBlockX = MVEA_LRB_SEARCH_WIDTH - (ui16SearchLeftOffset + 16); // this is our block position relative to the start of the LRB
   1655 
   1656     if ((iYPos = srcY = CurrentRowY - ui16SearchTopOffset) < 0)
   1657         srcY = 0;
   1658     else if (iYPos > ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16)
   1659         srcY = ctx->HeightMinusLRBSearchHeight;
   1660 
   1661 
   1662     /*DDK 243 removed this block of code.*/
   1663     /*if((ctx->eCodec==IMG_CODEC_H263_NO_RC)||(ctx->eCodec==IMG_CODEC_H263_CBR)||(ctx->eCodec==IMG_CODEC_H263_VBR))
   1664       ui16tmp = CurrentRowY;
   1665       else*/
   1666     ui16tmp = (CurrentRowY != SliceStartRowY);
   1667 
   1668     for (iPos = 0; iPos < ctx->Width; iPos += 16, psCurrent++) {
   1669         memset(psCurrent, 0, sizeof(MTX_CURRENT_IN_PARAMS));
   1670         psCurrent->MVValid = 0;
   1671         psCurrent->ParamsValid = 0;
   1672 
   1673         if (SliceStartRowY) {
   1674             psCurrent->MVValid = VECTORS_ABOVE_VALID;
   1675         }
   1676         /* Setup the parameters and motion vectors*/
   1677         if (ui16tmp) {
   1678             psCurrent->MVValid = VECTORS_ABOVE_VALID | DO_INTRA_PRED;
   1679             psCurrent->ParamsValid |= PARAMS_ABOVE_VALID;
   1680 
   1681             if (iPos + 16 < ctx->Width) {
   1682                 psCurrent->ParamsValid |= PARAMS_ABOVER_VALID;
   1683                 psCurrent->MVValid |= /*VECTORS_LEFT_VALID; //*/(1 << 2); /* Vectors left valid define looks wrong*/
   1684             }
   1685 
   1686             if (iPos > 0 && (iPos < ctx->Width)) {
   1687                 psCurrent->ParamsValid |= PARAMS_ABOVEL_VALID;
   1688                 psCurrent->MVValid |= VECTORS_ABOVE_LEFT_VALID; //(1<<0)
   1689             }
   1690         } else {
   1691             // are we the first MB in a new slice?
   1692             if (iPos == 0) {
   1693                 if ((ctx->eCodec == IMG_CODEC_H263_NO_RC) || (ctx->eCodec == IMG_CODEC_H263_CBR) || (ctx->eCodec == IMG_CODEC_H263_VBR)) {
   1694                     if (iYPos == -ui16SearchTopOffset)
   1695                         psCurrent->ParamsValid |= MB_START_OF_SLICE;// OPTI?
   1696                 } else {
   1697                     psCurrent->ParamsValid |= MB_START_OF_SLICE;// OPTI?
   1698                 }
   1699             }
   1700         }
   1701         /*DDK 243 removed this block of code.*/
   1702         /*if((ctx->eCodec==IMG_CODEC_H263_NO_RC) || (ctx->eCodec==IMG_CODEC_H263_CBR)||(ctx->eCodec==IMG_CODEC_H263_VBR))
   1703           {
   1704         // clear the above params valid bits
   1705         psCurrent->ParamsValid &=~(PARAMS_ABOVEL_VALID|PARAMS_ABOVER_VALID|PARAMS_ABOVE_VALID); // OPTI
   1706         }*/
   1707         // Have to fill in the right hand row of 4x4 vectors into the the left block
   1708         if (iPos) {
   1709             psCurrent->MVValid |= DO_INTRA_PRED | (1 << 3); /*MV_VALID define looks wrong?! so use hard coded value for now*/
   1710             psCurrent->ParamsValid |= 8; //(1<<3)
   1711         }
   1712         if (iPos == ctx->Width - 16) {
   1713             // indicate the last MB in a row
   1714             psCurrent->ParamsValid |= MB_END_OF_ROW;
   1715             // are we the last mb in the slice?
   1716             if (iYPos == (SliceStartRowY + SliceHeight - (ui16SearchTopOffset + 16))) {
   1717                 psCurrent->ParamsValid |= MB_END_OF_SLICE;
   1718                 if (iYPos == ctx->HeightMinus16MinusLRBTopOffset) {
   1719                     psCurrent->ParamsValid |= MB_END_OF_PICTURE;
   1720                 }
   1721             }
   1722         }
   1723         // And now the below block
   1724         // should do some kind of check to see if we are the first inter block, as otherwise the vectors will be invalid!
   1725         if (VectorsValid) {
   1726             if (iYPos < ctx->HeightMinus16MinusLRBTopOffset) {
   1727                 psCurrent->MVValid |= VECTORS_BELOW_VALID; //(1<<4)
   1728 
   1729                 if (iYPos < ctx->HeightMinus32MinusLRBTopOffset) {
   1730                     psCurrent->MVValid |= VECTORS_2BELOW_VALID; //(1<<5)
   1731                 }
   1732             }
   1733         }
   1734 
   1735         /*Set up IPEMin and Max for coordinate X in the search reference region*/
   1736         /*And set up flags in SPEMax when needed*/
   1737         if (iPos <= ui16SearchLeftOffset) {
   1738             psCurrent->IPEMin[0] = ui16CurBlockX - iPos;
   1739             psCurrent->RealEdge |= SPE_EDGE_LEFT;
   1740         } else {
   1741             psCurrent->IPEMin[0] = ui16CurBlockX / 16;
   1742         }
   1743 
   1744         if ((iPos + ui16SearchLeftOffset + 16) > ctx->Width) {
   1745             psCurrent->IPEMax[0] = (ui16CurBlockX - 1 + ctx->Width) - iPos; //(112 - 1) - ((iPos + 48+16) - ctx->psVideo->ui16Width);
   1746             psCurrent->RealEdge |= SPE_EDGE_RIGHT;
   1747         } else {
   1748             psCurrent->IPEMax[0] = (ui16CurBlockX + 16 + ui16SearchLeftOffset) - 1 - 3; //(112 - 1) - 3;
   1749         }
   1750 
   1751         /*Set up IPEMin and Max for Y coordinate in the search reference region*/
   1752         /*And set up flags in SPEMax when needed*/
   1753         if (iYPos <= 0) {
   1754             psCurrent->IPEMin[1] = 0;
   1755             psCurrent->RealEdge |= SPE_EDGE_TOP;
   1756         } else {
   1757             psCurrent->IPEMin[1] = 3;
   1758         }
   1759 
   1760         //Max Y
   1761         if (iYPos > ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16) {
   1762             psCurrent->IPEMax[1] = ui16SearchHeight - 1;
   1763             psCurrent->RealEdge |= ui16SearchHeight - 4;
   1764         } else {
   1765             psCurrent->IPEMax[1] = ui16SearchHeight - 4;
   1766         }
   1767 
   1768         psCurrent->CurBlockAddr = ((ui16CurBlockX) / 16);
   1769         psCurrent->CurBlockAddr |= ((IMG_UINT8)(((iYPos + ui16SearchTopOffset) - srcY) / 16) << 4);
   1770 
   1771         /* Setup the control register values
   1772            These will get setup and transferred to a different location within the macroblock parameter structure.
   1773            They are then read out of the esb by the mtx and used to control the hardware units
   1774            */
   1775         psCurrent->IPEControl = ctx->IPEControl;
   1776 
   1777         switch (ctx->eCodec) {
   1778         case IMG_CODEC_H263_NO_RC:
   1779         case IMG_CODEC_H263_VBR:
   1780         case IMG_CODEC_H263_CBR:
   1781             pnw__setup_qpvalues_mpeg4(psCurrent, bySliceQP);
   1782             psCurrent->JMCompControl = F_ENCODE(2, MVEA_CR_JMCOMP_MODE);
   1783             psCurrent->VLCControl = F_ENCODE(3, TOPAZ_VLC_CR_CODEC) | F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
   1784             break;
   1785         case IMG_CODEC_MPEG4_NO_RC:
   1786         case IMG_CODEC_MPEG4_VBR:
   1787         case IMG_CODEC_MPEG4_CBR:
   1788             pnw__setup_qpvalues_mpeg4(psCurrent, bySliceQP);
   1789             psCurrent->JMCompControl = F_ENCODE(1, MVEA_CR_JMCOMP_MODE) | F_ENCODE(1, MVEA_CR_JMCOMP_AC_ENABLE);
   1790             psCurrent->VLCControl = F_ENCODE(2, TOPAZ_VLC_CR_CODEC) | F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
   1791             break;
   1792         default:
   1793         case IMG_CODEC_H264_NO_RC:
   1794         case IMG_CODEC_H264_VBR:
   1795         case IMG_CODEC_H264_CBR:
   1796         case IMG_CODEC_H264_VCM:
   1797             pnw__setup_qpvalue_h264(psCurrent, bySliceQP);
   1798             psCurrent->JMCompControl = F_ENCODE(0, MVEA_CR_JMCOMP_MODE);
   1799             psCurrent->VLCControl = F_ENCODE(1, TOPAZ_VLC_CR_CODEC) | F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
   1800             break;
   1801         }
   1802     }
   1803 
   1804     // now setup the dummy end of frame macroblock.
   1805     if ((CurrentRowY + 16) >= ctx->Height) {
   1806         memset(psCurrent, 0, sizeof(MTX_CURRENT_IN_PARAMS));
   1807         psCurrent->MVValid = DO_INTRA_PRED;
   1808         psCurrent->ParamsValid = 0;
   1809         psCurrent->RealEdge = 0;
   1810     }
   1811 }
   1812 
   1813 void pnw_setup_slice_params(
   1814     context_ENC_p  ctx,
   1815     IMG_UINT16 YSliceStartPos,
   1816     IMG_UINT16 SliceHeight,
   1817     IMG_BOOL IsIntra,
   1818     IMG_BOOL  VectorsValid,
   1819     int bySliceQP)
   1820 {
   1821     IMG_UINT16 Rows, CurrentRowY;
   1822 
   1823     Rows = SliceHeight / 16;
   1824     CurrentRowY = YSliceStartPos;
   1825 
   1826     while (Rows) {
   1827         pnw__setup_slice_row_params(
   1828             ctx,
   1829             IsIntra,
   1830             CurrentRowY,
   1831             YSliceStartPos,
   1832             SliceHeight,
   1833             VectorsValid, bySliceQP);
   1834 
   1835         CurrentRowY += 16;
   1836         Rows--;
   1837     }
   1838 
   1839 }
   1840 
   1841 
   1842 
   1843 IMG_UINT32 pnw__send_encode_slice_params(
   1844     context_ENC_p ctx,
   1845     IMG_BOOL IsIntra,
   1846     IMG_UINT16 CurrentRow,
   1847     IMG_UINT8  DeblockIDC,
   1848     IMG_UINT32 FrameNum,
   1849     IMG_UINT16 SliceHeight,
   1850     IMG_UINT16 CurrentSlice)
   1851 {
   1852     SLICE_PARAMS *psSliceParams;
   1853     IMG_INT16 RowOffset;
   1854     IMG_UINT16 SearchHeight, SearchTopOffset;
   1855 
   1856     psb_buffer_p psCoded;
   1857     object_surface_p ref_surface;
   1858     psb_buffer_p psRef;
   1859     pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
   1860 
   1861 
   1862     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Send encode slice parmas, Is Intra:%d, CurrentRow:%d" \
   1863                              "DeblockIDC:%d, FrameNum:%d, SliceHeight:%d, CurrentSlice:%d\n",
   1864                              IsIntra, CurrentRow, DeblockIDC, FrameNum, SliceHeight, CurrentSlice);
   1865 
   1866     ref_surface = ctx->ref_surface;
   1867     psRef = &ctx->ref_surface->psb_surface->buf;
   1868     psCoded = ctx->coded_buf->psb_buffer;
   1869 
   1870     psSliceParams = (SLICE_PARAMS *)(cmdbuf->slice_params_p +
   1871                                      CurrentSlice * ((sizeof(SLICE_PARAMS) + 15) & 0xfff0));
   1872 
   1873     psSliceParams->SliceHeight = SliceHeight;
   1874     psSliceParams->SliceStartRowNum = CurrentRow / 16;
   1875     psSliceParams->ScanningIntraParams = (1 << SCANNING_INTRA_WIDTH_SHIFT) |
   1876         (1 << SCANNING_INTRA_STEP_SHIFT);
   1877 
   1878     /* We want multiple ones of these so we can submit multiple slices without having to wait for the next */
   1879     psSliceParams->Flags = 0;
   1880     psSliceParams->HostCtx = 0xdafed123;
   1881 
   1882 #ifdef VA_EMULATOR
   1883     psSliceParams->RefYStride = ref_surface->psb_surface->stride;
   1884     psSliceParams->RefUVStride = ref_surface->psb_surface->stride;
   1885     psSliceParams->RefYRowStride =  ref_surface->psb_surface->stride * 16;
   1886     psSliceParams->RefUVRowStride = ref_surface->psb_surface->stride * 16 / 2;
   1887 #else
   1888     psSliceParams->RefYStride = ref_surface->psb_surface->stride;
   1889     psSliceParams->RefUVStride = ref_surface->psb_surface->stride;
   1890     psSliceParams->RefYRowStride =  ref_surface->psb_surface->stride * 16;
   1891     psSliceParams->RefUVRowStride = ref_surface->psb_surface->stride * 16 / 2;
   1892 #endif
   1893     psSliceParams->NumAirMBs = ctx->num_air_mbs;
   1894     psSliceParams->AirThreshold = ctx->air_threshold;
   1895 
   1896     if (ctx->eCodec == IMG_CODEC_H264_VCM && ctx->max_slice_size == 0)
   1897         psSliceParams->MaxSliceSize = ctx->Width * ctx->Height * 12 / 2;
   1898     else
   1899         psSliceParams->MaxSliceSize = ctx->max_slice_size;
   1900     psSliceParams->FCode = ctx->FCode;/* Not clear yet, This field is not appare in firmware doc */
   1901 
   1902     SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, ctx->Height);
   1903     SearchTopOffset = (((SearchHeight / 2) / 16) * 16);
   1904 
   1905     RowOffset = CurrentRow - SearchTopOffset;
   1906     if (RowOffset <= 0)
   1907         RowOffset = 0;
   1908     if (RowOffset > (ctx->Height - SearchHeight))
   1909         RowOffset = (ctx->Height - SearchHeight);
   1910     if (!IsIntra) {
   1911         psSliceParams->Flags |= ISINTER_FLAGS;
   1912     }
   1913 
   1914     switch (DeblockIDC) {
   1915     case 0:
   1916         psSliceParams->Flags |= DEBLOCK_FRAME;
   1917         break;
   1918     case 2:
   1919         psSliceParams->Flags |= DEBLOCK_SLICE;
   1920         break;
   1921     case 1:
   1922     default:
   1923         // do nothing
   1924         break;
   1925     }
   1926 
   1927     switch (ctx->eCodec) {
   1928     case IMG_CODEC_H263_NO_RC:
   1929     case IMG_CODEC_H263_VBR:
   1930     case IMG_CODEC_H263_CBR:
   1931         psSliceParams->Flags |= ISH263_FLAGS;
   1932         break;
   1933     case IMG_CODEC_MPEG4_NO_RC:
   1934     case IMG_CODEC_MPEG4_VBR:
   1935     case IMG_CODEC_MPEG4_CBR:
   1936         psSliceParams->Flags |= ISMPEG4_FLAGS;
   1937         break;
   1938     case IMG_CODEC_H264_NO_RC:
   1939     case IMG_CODEC_H264_CBR:
   1940     case IMG_CODEC_H264_VCM:
   1941     case IMG_CODEC_H264_VBR:
   1942         psSliceParams->Flags |= ISH264_FLAGS;
   1943         break;
   1944     default:
   1945         psSliceParams->Flags |= ISH264_FLAGS;
   1946         printf("No format specified defaulting to h.264\n");
   1947         break;
   1948     }
   1949     /* we should also setup the interleaving requirements based on the source format */
   1950     if (ctx->eFormat == IMG_CODEC_PL12) /* FIXME contrary with old DDK, take notice */
   1951         psSliceParams->Flags |= INTERLEAVE_TARGET;
   1952 
   1953     cmdbuf = ctx->obj_context->pnw_cmdbuf;
   1954 
   1955     RELOC_SLICE_PARAMS_PNW(&(psSliceParams->RefYBase), 256 * RowOffset / 16, psRef);
   1956     RELOC_SLICE_PARAMS_PNW(&(psSliceParams->RefUVBase),
   1957                            ref_surface->psb_surface->stride * ref_surface->height + (RowOffset * 128 / 16),
   1958                            psRef);
   1959     if (IsIntra)
   1960         RELOC_SLICE_PARAMS_PNW(&(psSliceParams->InParamsBase),
   1961                                ctx->in_params_ofs,
   1962                                //((CurrentRow * (ctx->Width)) / 256 + ctx->obj_context->slice_count) * sizeof(MTX_CURRENT_IN_PARAMS),
   1963                                cmdbuf->topaz_in_params_I);
   1964     else
   1965         RELOC_SLICE_PARAMS_PNW(&(psSliceParams->InParamsBase),
   1966                                ctx->in_params_ofs,
   1967                                //((CurrentRow * (ctx->Width)) / 256 + ctx->obj_context->slice_count) * sizeof(MTX_CURRENT_IN_PARAMS),
   1968                                cmdbuf->topaz_in_params_P);
   1969 
   1970 #if  TOPAZ_PIC_PARAMS_VERBOSE
   1971     drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof psSliceParams %d\n", sizeof(*psSliceParams));
   1972     drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof MTX_CURRENT_IN_PARAMS %d\n", sizeof(MTX_CURRENT_IN_PARAMS));
   1973     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->SliceStartRowNum %d\n", psSliceParams->SliceStartRowNum);
   1974     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->SliceHeight %d\n", psSliceParams->SliceHeight);
   1975     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefYBase %x\n", psSliceParams->RefYBase);
   1976     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefUVBase %x\n", psSliceParams->RefUVBase);
   1977     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefYStride %d\n", psSliceParams->RefYStride);
   1978     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefUVStride %d\n", psSliceParams->RefUVStride);
   1979     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefYRowStride %d\n", psSliceParams->RefYRowStride);
   1980     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefUVRowStride %d\n", psSliceParams->RefUVRowStride);
   1981     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->HostCtx %x\n", psSliceParams->HostCtx);
   1982     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->Flags %x\n", psSliceParams->Flags);
   1983     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->MaxSliceSize %d\n",  psSliceParams->MaxSliceSize);
   1984     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->FCode %x\n", psSliceParams->FCode);
   1985     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->InParamsBase %x\n", psSliceParams->InParamsBase);
   1986     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->NumAirMBs %d\n", psSliceParams->NumAirMBs);
   1987     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->AirThreshold %x\n", psSliceParams->AirThreshold);
   1988     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->ScanningIntraParams %x\n", psSliceParams->ScanningIntraParams);
   1989 #endif
   1990 
   1991     pnw_cmdbuf_insert_command_package(ctx->obj_context,
   1992                                       ctx->SliceToCore,
   1993                                       MTX_CMDID_ENCODE_SLICE,
   1994                                       &cmdbuf->slice_params,
   1995                                       CurrentSlice *((sizeof(SLICE_PARAMS) + 15) & 0xfff0));
   1996 
   1997 
   1998     return 0;
   1999 }
   2000 
   2001 
   2002 
   2003 /*
   2004  * Function Name      : Reset_EncoderParams
   2005  * Description        : Reset Above & Below Params at the Start of Intra frame
   2006  */
   2007 void pnw_reset_encoder_params(context_ENC_p ctx)
   2008 {
   2009     unsigned char *Add_Below, *Add_Above;
   2010     pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
   2011 
   2012     /* all frames share the same Topaz param, in_param/aboveparam/bellow
   2013      * map it only when necessary
   2014      */
   2015     if (cmdbuf->topaz_above_params_p == NULL) {
   2016         VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_above_params, &cmdbuf->topaz_above_params_p);
   2017         if (vaStatus != VA_STATUS_SUCCESS) {
   2018             drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
   2019             return;
   2020         }
   2021     }
   2022 
   2023     if (cmdbuf->topaz_below_params_p == NULL) {
   2024         VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_below_params, &cmdbuf->topaz_below_params_p);
   2025         if (vaStatus != VA_STATUS_SUCCESS) {
   2026             drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
   2027             return;
   2028         }
   2029     }
   2030 
   2031     Add_Below = cmdbuf->topaz_below_params_p +
   2032                 ctx->below_params_ofs;
   2033 
   2034     memset(Add_Below, 0, ctx->below_params_size * 4);
   2035 
   2036     Add_Above = cmdbuf->topaz_above_params_p + ctx->above_params_ofs;
   2037     memset(Add_Above, 0, ctx->above_params_size * MAX_TOPAZ_CORES);
   2038 }
   2039 
   2040 
   2041 
   2042