Home | History | Annotate | Download | only in mrst
      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  *    Zeng Li <zeng.li (at) intel.com>
     27  *    Shengquan Yuan  <shengquan.yuan (at) intel.com>
     28  *    Binglin Chen <binglin.chen (at) intel.com>
     29  *
     30  */
     31 
     32 
     33 
     34 #include "psb_drv_video.h"
     35 
     36 #include "lnc_hostcode.h"
     37 #include "hwdefs/topaz_defs.h"
     38 #include "psb_def.h"
     39 #include "psb_cmdbuf.h"
     40 #include <stdio.h>
     41 #include "psb_output.h"
     42 #include <wsbm/wsbm_manager.h>
     43 #include "lnc_hostheader.h"
     44 #include "psb_drv_debug.h"
     45 
     46 #define ALIGN_TO(value, align) ((value + align - 1) & ~(align - 1))
     47 #define PAGE_ALIGN(value) ALIGN_TO(value, 4096)
     48 
     49 static VAStatus lnc__alloc_context_buffer(context_ENC_p ctx)
     50 {
     51     int width, height;
     52     VAStatus vaStatus = VA_STATUS_SUCCESS;
     53 
     54     /* width and height should be source surface's w and h or ?? */
     55     width = ctx->obj_context->picture_width;
     56     height = ctx->obj_context->picture_height;
     57 
     58     ctx->pic_params_size  = 256;
     59 
     60     ctx->header_buffer_size = 4 * HEADER_SIZE + MAX_SLICES_PER_PICTURE * HEADER_SIZE;
     61 
     62     ctx->seq_header_ofs = 0;
     63     ctx->pic_header_ofs = HEADER_SIZE;
     64     ctx->eoseq_header_ofs = 2 * HEADER_SIZE;
     65     ctx->eostream_header_ofs = 3 * HEADER_SIZE;
     66     ctx->slice_header_ofs = 4 * HEADER_SIZE;
     67 
     68     ctx->sliceparam_buffer_size = ((sizeof(SLICE_PARAMS) + 15) & 0xfff0) * MAX_SLICES_PER_PICTURE;
     69 
     70     /* All frame share same MTX_CURRENT_IN_PARAMS and above/bellow param
     71      * create MTX_CURRENT_IN_PARAMS buffer seperately
     72      * every MB has one MTX_CURRENT_IN_PARAMS structure, and the (N+1) frame can
     73      * reuse (N) frame's structure
     74      */
     75     ctx->in_params_size = (10 + width * height / (16 * 16)) * sizeof(MTX_CURRENT_IN_PARAMS);
     76     ctx->bellow_params_size = BELOW_PARAMS_SIZE * width * height / (16 * 16) * 16;
     77     ctx->above_params_size = (width * height / 16) * 128 + 15;
     78 
     79     ctx->topaz_buffer_size = ctx->in_params_size + /* MTX_CURRENT_IN_PARAMS size */
     80                              ctx->bellow_params_size + /* above_params */
     81                              ctx->above_params_size; /* above_params */
     82 
     83     vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->in_params_size, psb_bt_cpu_vpu, &ctx->topaz_in_params_I);
     84     vaStatus |= psb_buffer_create(ctx->obj_context->driver_data, ctx->in_params_size, psb_bt_cpu_vpu, &ctx->topaz_in_params_P);
     85     vaStatus |= psb_buffer_create(ctx->obj_context->driver_data, ctx->above_params_size + ctx->bellow_params_size, psb_bt_cpu_vpu, &ctx->topaz_above_bellow_params);
     86 
     87     ctx->in_params_ofs = 0;
     88     ctx->bellow_params_ofs = 0;
     89     ctx->above_params_ofs = ctx->bellow_params_ofs + ctx->bellow_params_size;
     90 
     91     return vaStatus;
     92 }
     93 
     94 unsigned int lnc__get_ipe_control(enum drm_lnc_topaz_codec  eEncodingFormat)
     95 {
     96     unsigned int RegVal = 0;
     97 
     98     RegVal = F_ENCODE(2, MVEA_CR_IPE_GRID_FINE_SEARCH) |
     99              F_ENCODE(0, MVEA_CR_IPE_GRID_SEARCH_SIZE) |
    100              F_ENCODE(1, MVEA_CR_IPE_Y_FINE_SEARCH);
    101 
    102     switch (eEncodingFormat) {
    103     case IMG_CODEC_H263_NO_RC:
    104     case IMG_CODEC_H263_VBR:
    105     case IMG_CODEC_H263_CBR:
    106         RegVal |= F_ENCODE(0, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(0, MVEA_CR_IPE_ENCODING_FORMAT);
    107         break;
    108     case IMG_CODEC_MPEG4_NO_RC:
    109     case IMG_CODEC_MPEG4_VBR:
    110     case IMG_CODEC_MPEG4_CBR:
    111         RegVal |= F_ENCODE(1, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(1, MVEA_CR_IPE_ENCODING_FORMAT);
    112     default:
    113         break;
    114     case IMG_CODEC_H264_NO_RC:
    115     case IMG_CODEC_H264_VBR:
    116     case IMG_CODEC_H264_CBR:
    117     case IMG_CODEC_H264_VCM:
    118         RegVal |= F_ENCODE(2, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(2, MVEA_CR_IPE_ENCODING_FORMAT);
    119         break;
    120     }
    121     RegVal |= F_ENCODE(6, MVEA_CR_IPE_Y_CANDIDATE_NUM);
    122     return RegVal;
    123 }
    124 
    125 
    126 void lnc_DestroyContext(object_context_p obj_context)
    127 {
    128     context_ENC_p ctx;
    129     ctx = (context_ENC_p)obj_context->format_data;
    130     if (NULL != ctx->slice_param_cache)
    131         free(ctx->slice_param_cache);
    132     if (NULL == ctx->save_seq_header_p)
    133         free(ctx->save_seq_header_p);
    134     free(obj_context->format_data);
    135     obj_context->format_data = NULL;
    136 }
    137 
    138 VAStatus lnc_CreateContext(
    139     object_context_p obj_context,
    140     object_config_p obj_config)
    141 {
    142     int width, height;
    143     context_ENC_p ctx;
    144     VAStatus vaStatus;
    145 
    146     width = obj_context->picture_width;
    147     height = obj_context->picture_height;
    148     ctx = (context_ENC_p) calloc(1, sizeof(struct context_ENC_s));
    149     if (NULL == ctx) {
    150         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    151         DEBUG_FAILURE;
    152         return vaStatus;
    153     }
    154 
    155     obj_context->format_data = (void*) ctx;
    156     ctx->obj_context = obj_context;
    157 
    158     ctx->RawWidth = (unsigned short) width;
    159     ctx->RawHeight = (unsigned short) height;
    160 
    161     ctx->Width = (unsigned short)(~0xf & (width + 0xf));
    162     ctx->Height = (unsigned short)(~0xf & (height + 0xf));
    163 
    164     ctx->HeightMinus16MinusLRBTopOffset = ctx->Height - (MVEA_LRB_TOP_OFFSET + 16);
    165     ctx->HeightMinus32MinusLRBTopOffset = ctx->Height - (MVEA_LRB_TOP_OFFSET + 32);
    166     ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16 = ctx->Height - (MVEA_LRB_TOP_OFFSET + MVEA_LRB_TOP_OFFSET + 16);
    167     ctx->HeightMinusLRBSearchHeight = ctx->Height - MVEA_LRB_SEARCH_HEIGHT;
    168 
    169     ctx->FCode = 0;
    170 
    171     ctx->sRCParams.VCMBitrateMargin = 0;
    172     ctx->sRCParams.BufferSize = 0;
    173     ctx->sRCParams.InitialQp = 0;
    174     ctx->sRCParams.MinQP = 0;
    175 
    176     vaStatus = lnc__alloc_context_buffer(ctx);
    177 
    178     return vaStatus;
    179 }
    180 
    181 
    182 VAStatus lnc_BeginPicture(context_ENC_p ctx)
    183 {
    184     VAStatus vaStatus = VA_STATUS_SUCCESS;
    185     lnc_cmdbuf_p cmdbuf;
    186     int ret;
    187 
    188     ctx->src_surface = ctx->obj_context->current_render_target;
    189 
    190     /* clear frameskip flag to 0 */
    191     CLEAR_SURFACE_INFO_skipped_flag(ctx->src_surface->psb_surface);
    192 
    193     /* Initialise the command buffer */
    194     ret = lnc_context_get_next_cmdbuf(ctx->obj_context);
    195     if (ret) {
    196         drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n");
    197         vaStatus = VA_STATUS_ERROR_UNKNOWN;
    198         return vaStatus;
    199     }
    200     cmdbuf = ctx->obj_context->lnc_cmdbuf;
    201 
    202     /* map start_pic param */
    203     vaStatus = psb_buffer_map(&cmdbuf->pic_params, &cmdbuf->pic_params_p);
    204     if (vaStatus) {
    205         return vaStatus;
    206     }
    207     vaStatus = psb_buffer_map(&cmdbuf->header_mem, &cmdbuf->header_mem_p);
    208     if (vaStatus) {
    209         psb_buffer_unmap(&cmdbuf->pic_params);
    210         return vaStatus;
    211     }
    212 
    213     vaStatus = psb_buffer_map(&cmdbuf->slice_params, &cmdbuf->slice_params_p);
    214     if (vaStatus) {
    215         psb_buffer_unmap(&cmdbuf->pic_params);
    216         psb_buffer_unmap(&cmdbuf->header_mem);
    217         return vaStatus;
    218     }
    219 
    220     /* only map topaz param when necessary */
    221     cmdbuf->topaz_in_params_I_p = NULL;
    222     cmdbuf->topaz_in_params_P_p = NULL;
    223     cmdbuf->topaz_above_bellow_params_p = NULL;
    224 
    225     if (ctx->obj_context->frame_count == 0) { /* first picture */
    226         psb_driver_data_p driver_data = ctx->obj_context->driver_data;
    227 
    228         lnc_cmdbuf_insert_command(cmdbuf, MTX_CMDID_SW_NEW_CODEC, 3, driver_data->drm_context);
    229         lnc_cmdbuf_insert_command_param(cmdbuf, ctx->eCodec);
    230         lnc_cmdbuf_insert_command_param(cmdbuf, (ctx->Width << 16) | ctx->Height);
    231     }
    232 
    233     /* insert START_PIC command */
    234     lnc_cmdbuf_insert_command(cmdbuf, MTX_CMDID_START_PIC, 3, ctx->obj_context->frame_count);
    235     /* write the address of structure PIC_PARAMS following command MTX_CMDID_START_PIC
    236      * the content of PIC_PARAMS is filled when RenderPicture(...,VAEncPictureParameterBufferXXX)
    237      */
    238     RELOC_CMDBUF(cmdbuf->cmd_idx, 0, &cmdbuf->pic_params);
    239     cmdbuf->cmd_idx++;
    240     ctx->initial_qp_in_cmdbuf = cmdbuf->cmd_idx; /* remember the place */
    241     cmdbuf->cmd_idx++;
    242 
    243     ctx->obj_context->slice_count = 0;
    244 
    245     /* no RC paramter provided in vaBeginPicture
    246      * so delay RC param setup into vaRenderPicture(SequenceHeader...)
    247      */
    248     return vaStatus;
    249 }
    250 
    251 
    252 VAStatus lnc_RenderPictureParameter(context_ENC_p ctx)
    253 {
    254     PIC_PARAMS *psPicParams;    /* PIC_PARAMS has been put in lnc_hostcode.h */
    255     object_surface_p src_surface;
    256     unsigned int srf_buf_offset;
    257     object_surface_p rec_surface;
    258     object_surface_p ref_surface;
    259     lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
    260     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
    261 
    262     psPicParams = (PIC_PARAMS *)cmdbuf->pic_params_p;
    263 
    264     /* second frame will reuse some rate control parameters (IN_PARAMS_MP4)
    265      * so only memset picture parames except IN_PARAMS
    266      * BUT now IN_RC_PARAMS was reload from the cache, so it now can
    267      * memset entirE PIC_PARAMS
    268      */
    269     memset(psPicParams, 0, (int)((unsigned char *)&psPicParams->sInParams - (unsigned char *)psPicParams));
    270 
    271     src_surface = ctx->src_surface;
    272     if (NULL == src_surface) {
    273         vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
    274         DEBUG_FAILURE;
    275         return vaStatus;
    276     }
    277 
    278     rec_surface = ctx->dest_surface;
    279     if (NULL == rec_surface) {
    280         vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
    281         DEBUG_FAILURE;
    282         return vaStatus;
    283     }
    284 
    285     /*The fisrt frame always is I frame and the content of reference frame wouldn't be used.
    286      * But the heights of ref and dest frame should be the same.
    287      * That allows Topaz to keep its motion vectors up to date, which helps maintain performance */
    288     if (ctx->obj_context->frame_count == 0)
    289         ctx->ref_surface = ctx->dest_surface;
    290 
    291     ref_surface = ctx->ref_surface;
    292     if (NULL == ref_surface) {
    293         vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
    294         DEBUG_FAILURE;
    295         return vaStatus;
    296     }
    297 
    298     /* clear frameskip flag */
    299     CLEAR_SURFACE_INFO_skipped_flag(rec_surface->psb_surface);
    300     CLEAR_SURFACE_INFO_skipped_flag(ref_surface->psb_surface);
    301 
    302     /* Write video data byte offset into Coded buffer
    303      * If it is here, it will be a SYNC point, which have performance impact
    304      * Move to psb__CreateBuffer
    305      vaStatus = psb_buffer_map(ctx->coded_buf->psb_buffer, &pBuffer);
    306      if(vaStatus) {
    307      DEBUG_FAILURE;
    308      return vaStatus;
    309      }
    310      *(IMG_UINT32 *)(pBuffer+8) = 16;
    311      psb_buffer_unmap(ctx->coded_buf->psb_buffer);
    312     */
    313 
    314     psPicParams->SrcYStride = src_surface->psb_surface->stride;
    315     switch (ctx->eFormat) {
    316     case IMG_CODEC_IYUV:        /* IYUV */
    317     case IMG_CODEC_PL8:
    318         psPicParams->SrcUVStride = src_surface->psb_surface->stride / 2;
    319         psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 16 / 2;
    320         break;
    321     case IMG_CODEC_IMC2:    /* IMC2 */
    322     case IMG_CODEC_PL12:
    323         psPicParams->SrcUVStride = src_surface->psb_surface->stride;
    324         psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 16;
    325         break;
    326     default:
    327         break;
    328     }
    329     psPicParams->SrcYRowStride    = src_surface->psb_surface->stride * 16;
    330     /* psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 16 / 2; */
    331 
    332     /* Dest(rec) stride
    333      * The are now literally Dst stride (not equivalent to 'offset to next row')
    334      */
    335 #ifdef VA_EMULATOR
    336     /* only for simulator, va-emulator needs the actually stride for
    337      * reconstructed frame transfer (va-emulator->driver)
    338      */
    339     psPicParams->DstYStride = rec_surface->psb_surface->stride;
    340     psPicParams->DstUVStride = rec_surface->psb_surface->stride;
    341     psPicParams->DstYRowStride = rec_surface->psb_surface->stride * 16;
    342     psPicParams->DstUVRowStride = rec_surface->psb_surface->stride * 16 / 2;
    343 #else
    344     psPicParams->DstYStride = rec_surface->height * 16;
    345     psPicParams->DstUVStride = rec_surface->height * 16 / 2;
    346     psPicParams->DstYRowStride = psPicParams->DstYStride;
    347     psPicParams->DstUVRowStride = psPicParams->DstUVStride;
    348 #endif
    349 
    350     psPicParams->InParamsRowStride = (ctx->obj_context->picture_width / 16) * 256;
    351     psPicParams->BelowParamRowStride = (ctx->obj_context->picture_width / 16) * 32;
    352 
    353     psPicParams->Width  = ctx->Width;
    354     psPicParams->Height = ctx->Height;
    355 
    356     /* not sure why we are setting this up here... */
    357     psPicParams->Flags = 0;
    358     switch (ctx->eCodec) {
    359     case IMG_CODEC_H264_NO_RC:
    360     case IMG_CODEC_H264_VBR:
    361     case IMG_CODEC_H264_CBR:
    362     case IMG_CODEC_H264_VCM:
    363         psPicParams->Flags |= ISH264_FLAGS;
    364         break;
    365     case IMG_CODEC_H263_VBR:
    366     case IMG_CODEC_H263_CBR:
    367     case IMG_CODEC_H263_NO_RC:
    368         psPicParams->Flags |= ISH263_FLAGS;
    369         break;
    370     case IMG_CODEC_MPEG4_NO_RC:
    371     case IMG_CODEC_MPEG4_VBR:
    372     case IMG_CODEC_MPEG4_CBR:
    373         psPicParams->Flags |= ISMPEG4_FLAGS;
    374         break;
    375     default:
    376         return VA_STATUS_ERROR_UNKNOWN;
    377     }
    378 
    379     switch (ctx->eCodec) {
    380     case IMG_CODEC_H264_VBR:
    381     case IMG_CODEC_MPEG4_VBR:
    382     case IMG_CODEC_H263_VBR:
    383         psPicParams->Flags |= ISVBR_FLAGS;
    384         break;
    385     case IMG_CODEC_H264_VCM:
    386         psPicParams->Flags |= ISVCM_FLAGS;
    387         /* drop through to CBR case */
    388     case IMG_CODEC_H263_CBR:
    389     case IMG_CODEC_H264_CBR:
    390     case IMG_CODEC_MPEG4_CBR:
    391         psPicParams->Flags |= ISCBR_FLAGS;
    392         break;
    393     case IMG_CODEC_MPEG4_NO_RC:
    394     case IMG_CODEC_H263_NO_RC:
    395     case IMG_CODEC_H264_NO_RC:
    396         break;
    397     default:
    398         return VA_STATUS_ERROR_UNKNOWN;
    399     }
    400 
    401 
    402     if (ctx->sRCParams.RCEnable) {
    403         /* for the first frame, will setup RC params in EndPicture */
    404         if (ctx->obj_context->frame_count > 0) { /* reuse in_params parameter */
    405             /* reload IN_RC_PARAMS from cache */
    406             memcpy(&psPicParams->sInParams, &ctx->in_params_cache, sizeof(IN_RC_PARAMS));
    407 
    408             /* delay these into END_PICTURE timeframe */
    409             /*
    410             psPicParams->sInParams.BitsTransmitted = ctx->sRCParams.BitsTransmitted;
    411             */
    412         }
    413     } else
    414         psPicParams->sInParams.SeInitQP = ctx->sRCParams.InitialQp;
    415 
    416     /* some relocations have to been done here */
    417     srf_buf_offset = src_surface->psb_surface->buf.buffer_ofs;
    418     if (src_surface->psb_surface->buf.type == psb_bt_camera)
    419         drv_debug_msg(VIDEO_DEBUG_GENERAL, "src surface GPU offset 0x%08x, luma offset 0x%08x\n",
    420                                  wsbmBOOffsetHint(src_surface->psb_surface->buf.drm_buf), srf_buf_offset);
    421 
    422     RELOC_PIC_PARAMS(&psPicParams->SrcYBase, srf_buf_offset, &src_surface->psb_surface->buf);
    423     switch (ctx->eFormat) {
    424     case IMG_CODEC_IYUV:
    425     case IMG_CODEC_PL8:
    426     case IMG_CODEC_PL12:
    427         RELOC_PIC_PARAMS(&psPicParams->SrcUBase,
    428                          srf_buf_offset + src_surface->psb_surface->chroma_offset,
    429                          &src_surface->psb_surface->buf);
    430 
    431         RELOC_PIC_PARAMS(&psPicParams->SrcVBase,
    432                          srf_buf_offset + src_surface->psb_surface->chroma_offset,
    433                          &src_surface->psb_surface->buf);
    434 
    435         break;
    436     case IMG_CODEC_IMC2:
    437     case IMG_CODEC_NV12:
    438         break;
    439     }
    440 
    441     /*
    442      * Do not forget this!
    443      * MTXWriteMem(MTXData.ui32CCBCtrlAddr + MTX_CCBCTRL_QP, sRCParams.ui32InitialQp);
    444      */
    445     /* following START_PIC, insert initial QP */
    446     *ctx->initial_qp_in_cmdbuf = ctx->sRCParams.InitialQp;
    447 
    448 
    449     RELOC_PIC_PARAMS(&psPicParams->DstYBase, 0, &rec_surface->psb_surface->buf);
    450 
    451     RELOC_PIC_PARAMS(&psPicParams->DstUVBase,
    452                      rec_surface->psb_surface->stride * rec_surface->height,
    453                      &rec_surface->psb_surface->buf);
    454 
    455     RELOC_PIC_PARAMS(&psPicParams->CodedBase, 0, ctx->coded_buf->psb_buffer);
    456 
    457     /* MTX_CURRENT_IN_PARAMS buffer is seperate buffer now */
    458     /*The type of frame will decide psPicParams->InParamsBase should
    459      * use cmdbuf->topaz_in_params_P or cmdbuf->topaz_in_params_I*/
    460     /*RELOC_PIC_PARAMS(&psPicParams->InParamsBase, ctx->in_params_ofs, cmdbuf->topaz_in_params_P);*/
    461     RELOC_PIC_PARAMS(&psPicParams->BelowParamsBase, ctx->bellow_params_ofs, cmdbuf->topaz_above_bellow_params);
    462     RELOC_PIC_PARAMS(&psPicParams->AboveParamsBase, ctx->above_params_ofs, cmdbuf->topaz_above_bellow_params);
    463 
    464     return VA_STATUS_SUCCESS;
    465 }
    466 
    467 static VAStatus lnc__PatchBitsConsumedInRCParam(context_ENC_p ctx)
    468 {
    469     lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
    470     /* PIC_PARAMS  *psPicParams = cmdbuf->pic_params_p; */
    471     VAStatus vaStatus;
    472 
    473     (void)cmdbuf;
    474     /* it will wait until last encode session is done */
    475     /* now it just wait the last session is done and the frame skip
    476      * is  */
    477     drv_debug_msg(VIDEO_DEBUG_GENERAL, "will patch bits consumed for rc\n");
    478     if (ctx->pprevious_coded_buf) {
    479         vaStatus = psb_buffer_sync(ctx->pprevious_coded_buf->psb_buffer);
    480         if (vaStatus)
    481             return vaStatus;
    482     }
    483 
    484     return VA_STATUS_SUCCESS;
    485 }
    486 
    487 static VAStatus lnc_RedoRenderPictureSkippedFrame(context_ENC_p ctx)
    488 {
    489     lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
    490     VAStatus vaStatus = VA_STATUS_SUCCESS;
    491     int i = 0;
    492 
    493     /* reset cmdbuf to skip existing picture/slice DO_HEAD commands */
    494     cmdbuf->cmd_idx = cmdbuf->cmd_idx_saved_frameskip;
    495 
    496     switch (ctx->eCodec) {
    497     case IMG_CODEC_H263_CBR: /* H263 don't need picture header/slice header, only reset command buf */
    498     case IMG_CODEC_H263_VBR:
    499         break;
    500     case IMG_CODEC_H264_VBR:
    501     case IMG_CODEC_H264_CBR: /* slice header needs redo */
    502     case IMG_CODEC_H264_VCM: {
    503         /* only need one slice header here */
    504         VAEncSliceParameterBuffer *pBuffer = &ctx->slice_param_cache[i];
    505         unsigned int MBSkipRun, FirstMBAddress;
    506         int deblock_on;
    507 
    508         if ((pBuffer->slice_flags.bits.disable_deblocking_filter_idc == 0)
    509             || (pBuffer->slice_flags.bits.disable_deblocking_filter_idc == 2))
    510             deblock_on = IMG_TRUE;
    511         else
    512             deblock_on = IMG_FALSE;
    513 
    514         if (1 /* ctx->sRCParams.RCEnable && ctx->sRCParams.FrameSkip */) /* we know it is true */
    515             MBSkipRun = (ctx->Width * ctx->Height) / 256;
    516         else
    517             MBSkipRun = 0;
    518 
    519         FirstMBAddress = (pBuffer->start_row_number * ctx->Width) / 16;
    520         /* Insert Do Header command, relocation is needed */
    521 
    522         lnc__H264_prepare_slice_header((IMG_UINT32 *)(cmdbuf->header_mem_p + ctx->slice_header_ofs + i * HEADER_SIZE),
    523                                        0, /*pBuffer->slice_flags.bits.is_intra*/
    524                                        pBuffer->slice_flags.bits.disable_deblocking_filter_idc,
    525                                        ctx->obj_context->frame_count,
    526                                        FirstMBAddress,
    527                                        MBSkipRun,
    528                                        (ctx->obj_context->frame_count == 0),
    529                                        pBuffer->slice_flags.bits.uses_long_term_ref,
    530                                        pBuffer->slice_flags.bits.is_long_term_ref,
    531                                        ctx->idr_pic_id);
    532 
    533 
    534         lnc_cmdbuf_insert_command(cmdbuf, MTX_CMDID_DO_HEADER, 2, (i << 2) | 2);
    535         RELOC_CMDBUF(cmdbuf->cmd_idx++,
    536                      ctx->slice_header_ofs + i * HEADER_SIZE,
    537                      &cmdbuf->header_mem);
    538     }
    539 
    540     break;
    541     case IMG_CODEC_MPEG4_VBR:
    542     case IMG_CODEC_MPEG4_CBR: /* only picture header need redo */
    543         lnc__MPEG4_prepare_vop_header((IMG_UINT32 *)(cmdbuf->header_mem_p + ctx->pic_header_ofs),
    544                                       IMG_FALSE /* bIsVOPCoded is false now */,
    545                                       ctx->MPEG4_vop_time_increment_frameskip, /* In testbench, this should be FrameNum */
    546                                       4,/* default value is 4,search range */
    547                                       ctx->MPEG4_picture_type_frameskip,
    548                                       ctx->MPEG4_vop_time_increment_resolution/* defaule value */);
    549 
    550         lnc_cmdbuf_insert_command(cmdbuf, MTX_CMDID_DO_HEADER, 2, 1);
    551         RELOC_CMDBUF(cmdbuf->cmd_idx++, ctx->pic_header_ofs, &cmdbuf->header_mem);
    552         vaStatus = lnc_RenderPictureParameter(ctx);
    553         break;
    554     default:
    555         drv_debug_msg(VIDEO_DEBUG_ERROR, "Non-RC mode should be here for FrameSkip handling\n");
    556         ASSERT(0);
    557     }
    558 
    559     return vaStatus;
    560 }
    561 
    562 static VAStatus lnc_SetupRCParam(context_ENC_p ctx)
    563 {
    564     lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
    565     PIC_PARAMS  *psPicParams = (PIC_PARAMS  *)cmdbuf->pic_params_p;
    566     int origin_qp;/* in DDK setup_rc will change qp strangly,
    567                    * just for keep same with DDK
    568                    */
    569 
    570     origin_qp = ctx->sRCParams.InitialQp;
    571 
    572     drv_debug_msg(VIDEO_DEBUG_GENERAL, "will setup rc data\n");
    573 
    574     psPicParams->Flags |= ISRC_FLAGS;
    575     lnc__setup_rcdata(ctx, psPicParams, &ctx->sRCParams);
    576 
    577     /* restore it, just keep same with DDK */
    578     ctx->sRCParams.InitialQp = origin_qp;
    579 
    580     /* save IN_RC_PARAMS into the cache */
    581     memcpy(&ctx->in_params_cache, (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
    582 
    583     return VA_STATUS_SUCCESS;
    584 }
    585 
    586 static VAStatus lnc_UpdateRCParam(context_ENC_p ctx)
    587 {
    588     int origin_qp;
    589     lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
    590     PIC_PARAMS  *psPicParams = (PIC_PARAMS  *)cmdbuf->pic_params_p;
    591 
    592     origin_qp = ctx->sRCParams.InitialQp;
    593 
    594     drv_debug_msg(VIDEO_DEBUG_GENERAL, "will update rc data\n");
    595     lnc__update_rcdata(ctx, psPicParams, &ctx->sRCParams);
    596 
    597     /* set minQP if hosts set minQP */
    598     if (ctx->sRCParams.MinQP)
    599         psPicParams->sInParams.MinQPVal = ctx->sRCParams.MinQP;
    600 
    601     /* if seinitqp is set, restore the value hosts want */
    602     if (origin_qp) {
    603         psPicParams->sInParams.SeInitQP = origin_qp;
    604         psPicParams->sInParams.MyInitQP = origin_qp;
    605         ctx->sRCParams.InitialQp = origin_qp;
    606     }
    607 
    608     /* save IN_RC_PARAMS into the cache */
    609     memcpy(&ctx->in_params_cache, (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
    610 
    611     return VA_STATUS_SUCCESS;
    612 }
    613 
    614 static VAStatus lnc_PatchRCMode(context_ENC_p ctx)
    615 {
    616     int frame_skip = 0;
    617 
    618     drv_debug_msg(VIDEO_DEBUG_GENERAL, "will patch rc data\n");
    619     /* it will ensure previous encode finished */
    620     lnc__PatchBitsConsumedInRCParam(ctx);
    621 
    622     /* get frameskip flag */
    623     lnc_surface_get_frameskip(ctx->obj_context->driver_data, ctx->src_surface->psb_surface, &frame_skip);
    624     /* current frame is skipped
    625      * redo RenderPicture with FrameSkip set
    626      */
    627     if (frame_skip == 1)
    628         lnc_RedoRenderPictureSkippedFrame(ctx);
    629 
    630     return VA_STATUS_SUCCESS;
    631 }
    632 
    633 VAStatus lnc_EndPicture(context_ENC_p ctx)
    634 {
    635     VAStatus vaStatus = VA_STATUS_SUCCESS;
    636     lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
    637 
    638     if (ctx->sRCParams.RCEnable == IMG_TRUE) {
    639         if (ctx->obj_context->frame_count == 0)
    640             lnc_SetupRCParam(ctx);
    641         else if (ctx->update_rc_control)
    642             lnc_UpdateRCParam(ctx);
    643         else
    644             lnc_PatchRCMode(ctx);
    645     }
    646     ctx->update_rc_control = 0;
    647 
    648     /* save current settings */
    649     ctx->previous_src_surface = ctx->src_surface;
    650     ctx->previous_ref_surface = ctx->ref_surface;
    651     ctx->previous_dest_surface = ctx->dest_surface; /* reconstructed surface */
    652     ctx->pprevious_coded_buf = ctx->previous_coded_buf;
    653     ctx->previous_coded_buf = ctx->coded_buf;
    654 
    655     lnc_cmdbuf_insert_command(cmdbuf, MTX_CMDID_END_PIC, 3, 0);
    656     lnc_cmdbuf_insert_command_param(cmdbuf, 0);/* two meaningless parameters */
    657     lnc_cmdbuf_insert_command_param(cmdbuf, 0);
    658     psb_buffer_unmap(&cmdbuf->pic_params);
    659     psb_buffer_unmap(&cmdbuf->header_mem);
    660     psb_buffer_unmap(&cmdbuf->slice_params);
    661 
    662     /* unmap MTX_CURRENT_IN_PARAMS buffer only when it is mapped */
    663     if (cmdbuf->topaz_in_params_I_p != NULL) {
    664         psb_buffer_unmap(cmdbuf->topaz_in_params_I);
    665         cmdbuf->topaz_in_params_I_p = NULL;
    666     }
    667 
    668     if (cmdbuf->topaz_in_params_P_p != NULL) {
    669         psb_buffer_unmap(cmdbuf->topaz_in_params_P);
    670         cmdbuf->topaz_in_params_P_p = NULL;
    671     }
    672 
    673     if (cmdbuf->topaz_above_bellow_params_p != NULL) {
    674         psb_buffer_unmap(cmdbuf->topaz_above_bellow_params);
    675         cmdbuf->topaz_above_bellow_params_p = NULL;
    676     }
    677 
    678     if (lnc_context_flush_cmdbuf(ctx->obj_context)) {
    679         vaStatus = VA_STATUS_ERROR_UNKNOWN;
    680     }
    681 
    682     return vaStatus;
    683 }
    684 
    685 static void lnc__setup_busize(context_ENC_p ctx)
    686 {
    687     unsigned int old_busize = ctx->sRCParams.BUSize;
    688 
    689     /* it is called at EndPicture, we should now the Slice number */
    690     ctx->Slices = ctx->obj_context->slice_count;
    691 
    692     /* if no BU size is given then pick one ourselves */
    693     if (ctx->sRCParams.BUSize != 0)  { /* application provided BUSize */
    694         IMG_UINT32 MBs, MBsperSlice, MBsLastSlice;
    695         IMG_UINT32 BUs;
    696         IMG_INT32  SliceHeight;
    697 
    698         MBs     = ctx->Height * ctx->Width / (16 * 16);
    699 
    700         SliceHeight     = ctx->Height / ctx->Slices;
    701         /* SliceHeight += 15; */
    702         SliceHeight &= ~15;
    703 
    704         MBsperSlice     = (SliceHeight * ctx->Width) / (16 * 16);
    705         MBsLastSlice    = MBs - (MBsperSlice * (ctx->Slices - 1));
    706 
    707         /* they have given us a basic unit so validate it */
    708         if (ctx->sRCParams.BUSize < 6) {
    709             drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too small, must be greater than 6\n");
    710             ctx->sRCParams.BUSize = 0; /* need repatch */;
    711         }
    712         if (ctx->sRCParams.BUSize > MBsperSlice) {
    713             drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too large, must be less than the number of macroblocks in a slice\n");
    714             ctx->sRCParams.BUSize = 0; /* need repatch */;
    715         }
    716         if (ctx->sRCParams.BUSize > MBsLastSlice) {
    717             drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too large, must be less than number of macroblocks in the last slice\n");
    718             ctx->sRCParams.BUSize = 0; /* need repatch */;
    719         }
    720         BUs = MBsperSlice / ctx->sRCParams.BUSize;
    721         if ((BUs * ctx->sRCParams.BUSize) != MBsperSlice)   {
    722             drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size not an integer divisor of MB's in a slice");
    723             ctx->sRCParams.BUSize = 0; /* need repatch */;
    724         }
    725         if (BUs > 200) {
    726             drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too small. There must be less than 200 basic units per slice");
    727             ctx->sRCParams.BUSize = 0; /* need repatch */;
    728         }
    729         BUs = MBsLastSlice / ctx->sRCParams.BUSize;
    730         if (BUs > 200) {
    731             drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too small. There must be less than 200 basic units per slice");
    732             ctx->sRCParams.BUSize = 0; /* need repatch */;
    733         }
    734     }
    735 
    736     if (ctx->sRCParams.BUSize == 0)  {
    737         IMG_UINT32 MBs, MBsperSlice, MBsLastSlice;
    738         IMG_UINT32 BUs, BUsperSlice, BUsLastSlice;
    739         IMG_INT32  SliceHeight;
    740 
    741         MBs     = ctx->Height * ctx->Width / (16 * 16);
    742 
    743         SliceHeight     = ctx->Height / ctx->Slices;
    744         /* SliceHeight += 15; */
    745         SliceHeight &= ~15;
    746 
    747         MBsperSlice     = (SliceHeight * ctx->Width) / (16 * 16);
    748         MBsLastSlice = MBs - (MBsperSlice * (ctx->Slices - 1));
    749 
    750         /* we have to verify that MBs is divisiable by BU AND that BU is > pipeline length */
    751         if (ctx->sRCParams.BUSize < 6)  {
    752             ctx->sRCParams.BUSize = 6;
    753         }
    754 
    755         BUs = MBs / ctx->sRCParams.BUSize;
    756         while (BUs*ctx->sRCParams.BUSize != MBs) {
    757             ctx->sRCParams.BUSize++;
    758             BUs = MBs / ctx->sRCParams.BUSize;
    759         }
    760 
    761         /* Check number of BUs in the pipe is less than maximum number allowed 200  */
    762         BUsperSlice = MBsperSlice / ctx->sRCParams.BUSize;
    763         BUsLastSlice = MBsLastSlice / ctx->sRCParams.BUSize;
    764         while ((BUsperSlice  *(ctx->Slices - 1) + BUsLastSlice) > 200)  {
    765             ctx->sRCParams.BUSize++;
    766             BUsperSlice = MBsperSlice / ctx->sRCParams.BUSize;
    767             BUsLastSlice = MBsLastSlice / ctx->sRCParams.BUSize;
    768         }
    769 
    770         /* Check whether there are integer number of BUs in the slices  */
    771         BUsperSlice = MBsperSlice / ctx->sRCParams.BUSize;
    772         BUsLastSlice = MBsLastSlice / ctx->sRCParams.BUSize;
    773         while ((BUsperSlice*ctx->sRCParams.BUSize != MBsperSlice) ||
    774                (BUsLastSlice*ctx->sRCParams.BUSize != MBsLastSlice))   {
    775             ctx->sRCParams.BUSize++;
    776             BUsperSlice = MBsperSlice / ctx->sRCParams.BUSize;
    777             BUsLastSlice = MBsLastSlice / ctx->sRCParams.BUSize;
    778         }
    779 
    780         if (ctx->sRCParams.BUSize != old_busize)
    781             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Patched Basic unit to %d (original=%d)\n", ctx->sRCParams.BUSize, old_busize);
    782     }
    783 }
    784 
    785 
    786 /***********************************************************************************
    787  * Function Name      : SetupRCData
    788  * Inputs             :
    789  * Outputs            :
    790  * Returns            :
    791  * Description        : Sets up RC Data
    792  ************************************************************************************/
    793 void lnc__setup_rcdata(
    794     context_ENC_p psContext,
    795     PIC_PARAMS *psPicParams,
    796     IMG_RC_PARAMS *psRCParams)
    797 {
    798     IMG_UINT32   max_bitrate = psContext->Width * psContext->Height * 1.5 * 8 * 60;
    799     IMG_UINT8 InitialSeInitQP = 0;
    800 
    801     /* frameskip is always cleared, specially handled at vaEndPicture */
    802     psRCParams->FrameSkip = 0;
    803 
    804     if (!psRCParams->BitsPerSecond)
    805         psRCParams->BitsPerSecond = 64000;
    806     if (psRCParams->BitsPerSecond > max_bitrate)
    807         psRCParams->BitsPerSecond = max_bitrate;
    808 
    809     if (!psRCParams->FrameRate)
    810         psRCParams->FrameRate = 30;
    811 
    812     if (psRCParams->BufferSize == 0) {
    813         if (psRCParams->BitsPerSecond < 256000)
    814             psRCParams->BufferSize = (9 * psRCParams->BitsPerSecond) >> 1;
    815         else
    816             psRCParams->BufferSize = (5 * psRCParams->BitsPerSecond) >> 1;
    817     }
    818     psRCParams->InitialLevel = (3 * psRCParams->BufferSize) >> 4;
    819     psRCParams->InitialDelay = (13 * psRCParams->BufferSize) >> 4;
    820 
    821     lnc__setup_busize(psContext); /* calculate BasicUnitSize */
    822 
    823     psPicParams->sInParams.SeInitQP = psRCParams->InitialQp;
    824 
    825     psPicParams->sInParams.MBPerRow = (psContext->Width >> 4);
    826     psPicParams->sInParams.MBPerBU = psRCParams->BUSize;
    827     psPicParams->sInParams.MBPerFrm     = (psContext->Width >> 4) * (psContext->Height >> 4);
    828     psPicParams->sInParams.BUPerFrm     = (psPicParams->sInParams.MBPerFrm) / psRCParams->BUSize;
    829 
    830     InitialSeInitQP = psPicParams->sInParams.SeInitQP;
    831 
    832     lnc__update_rcdata(psContext, psPicParams, psRCParams);
    833     /* set minQP if hosts set minQP */
    834     if (psRCParams->MinQP)
    835         psPicParams->sInParams.MinQPVal = psRCParams->MinQP;
    836 
    837     /* if seinitqp is set, restore the value hosts want */
    838     if (InitialSeInitQP) {
    839         psPicParams->sInParams.SeInitQP = InitialSeInitQP;
    840         psPicParams->sInParams.MyInitQP = InitialSeInitQP;
    841         psRCParams->InitialQp = InitialSeInitQP;
    842     }
    843 }
    844 
    845 void lnc__update_rcdata(context_ENC_p psContext,
    846                         PIC_PARAMS *psPicParams,
    847                         IMG_RC_PARAMS *psRCParams)
    848 {
    849     double              L1, L2, L3, L4, L5, flBpp;
    850     INT16               i16TempQP;
    851     IMG_INT32   i32BufferSizeInFrames;
    852 
    853     flBpp                                                                       = 1.0 * psRCParams->BitsPerSecond / (psRCParams->FrameRate * psContext->Width * psContext->Height);
    854 
    855     /* recalculate for small frames */
    856     if (psContext->Width <= 176)
    857         flBpp = flBpp / 2.0;
    858 
    859     psPicParams->sInParams.IntraPeriod  = psRCParams->IntraFreq;
    860     psPicParams->sInParams.BitRate              = psRCParams->BitsPerSecond;
    861     psPicParams->sInParams.IntraPeriod  = psRCParams->IntraFreq;
    862 
    863     psPicParams->sInParams.BitsPerFrm   = psRCParams->BitsPerSecond / psRCParams->FrameRate;
    864     psPicParams->sInParams.BitsPerGOP   = psPicParams->sInParams.BitsPerFrm * psRCParams->IntraFreq;
    865     psPicParams->sInParams.BitsPerBU            = psPicParams->sInParams.BitsPerFrm / (4 * psPicParams->sInParams.BUPerFrm);
    866     psPicParams->sInParams.BitsPerMB            = psPicParams->sInParams.BitsPerBU / psRCParams->BUSize;
    867 
    868     i32BufferSizeInFrames = psRCParams->BufferSize / psPicParams->sInParams.BitsPerFrm;
    869 
    870     // select thresholds and initial Qps etc that are codec dependent
    871     switch (psContext->eCodec) {
    872     case IMG_CODEC_H264_CBR:
    873     case IMG_CODEC_H264_VCM:
    874     case IMG_CODEC_H264_VBR:
    875         L1 = 0.1;
    876         L2 = 0.15;
    877         L3 = 0.2;
    878         psPicParams->sInParams.MaxQPVal = 51;
    879 
    880         // Set THSkip Values
    881         if (flBpp <= 0.07)
    882             psPicParams->THSkip = TH_SKIP_24;
    883         else if (flBpp <= 0.14)
    884             psPicParams->THSkip = TH_SKIP_12;
    885         else
    886             psPicParams->THSkip = TH_SKIP_0;
    887 
    888         if (flBpp <= 0.3)
    889             psPicParams->Flags |= ISRC_I16BIAS;
    890 
    891         // Setup MAX and MIN Quant Values
    892         if (flBpp >= 0.50)
    893             i16TempQP = 4;
    894         else if (flBpp > 0.133)
    895             i16TempQP = (unsigned int)(24 - (40 * flBpp));
    896         else
    897             i16TempQP = (unsigned int)(32 - (100 * flBpp));
    898 
    899         psPicParams->sInParams.MinQPVal = (max(min(psPicParams->sInParams.MaxQPVal, i16TempQP), 0));
    900         // Calculate Initial QP if it has not been specified
    901 
    902         L1 = 0.050568;
    903         L2 = 0.202272;
    904         L3 = 0.40454321;
    905         L4 = 0.80908642;
    906         L5 = 1.011358025;
    907         if (flBpp < L1)
    908             i16TempQP = (IMG_INT16)(47 - 78.10 * flBpp);
    909 
    910         else if (flBpp >= L1 && flBpp < L2)
    911             i16TempQP = (IMG_INT16)(46 - 72.51 * flBpp);
    912 
    913         else if (flBpp >= L2 && flBpp < L3)
    914             i16TempQP = (IMG_INT16)(36 - 24.72 * flBpp);
    915 
    916         else if (flBpp >= L3 && flBpp < L4)
    917             i16TempQP = (IMG_INT16)(34 - 19.78 * flBpp);
    918 
    919         else if (flBpp >= L4 && flBpp < L5)
    920             i16TempQP = (IMG_INT16)(27 - 9.89 * flBpp);
    921 
    922         else if (flBpp >= L5)
    923             i16TempQP = (IMG_INT16)(20 - 4.95 * flBpp);
    924 
    925         psPicParams->sInParams.SeInitQP = (IMG_UINT8)(max(min(psPicParams->sInParams.MaxQPVal, i16TempQP), 0));
    926         break;
    927 
    928     case IMG_CODEC_MPEG4_CBR:
    929     case IMG_CODEC_MPEG4_VBR:
    930         psPicParams->sInParams.MaxQPVal  = 31;
    931 
    932         if (psContext->Width == 176) {
    933             L1 = 0.1;
    934             L2 = 0.3;
    935             L3 = 0.6;
    936         } else if (psContext->Width == 352) {
    937             L1 = 0.2;
    938             L2 = 0.6;
    939             L3 = 1.2;
    940         } else {
    941             L1 = 0.25;
    942             L2 = 1.4;
    943             L3 = 2.4;
    944         }
    945 
    946         // Calculate Initial QP if it has not been specified
    947         if (flBpp <= L1)
    948             psPicParams->sInParams.SeInitQP = 31;
    949         else {
    950             if (flBpp <= L2)
    951                 psPicParams->sInParams.SeInitQP = 25;
    952             else
    953                 psPicParams->sInParams.SeInitQP = (flBpp <= L3) ? 20 : 10;
    954         }
    955 
    956         if (flBpp >= 0.25) {
    957             psPicParams->sInParams.MinQPVal = 1;
    958         } else {
    959             psPicParams->sInParams.MinQPVal = 2;
    960         }
    961         break;
    962 
    963     case IMG_CODEC_H263_CBR:
    964     case IMG_CODEC_H263_VBR:
    965         psPicParams->sInParams.MaxQPVal  = 31;
    966 
    967         if (psContext->Width == 176) {
    968             L1 = 0.1;
    969             L2 = 0.3;
    970             L3 = 0.6;
    971         } else if (psContext->Width == 352) {
    972             L1 = 0.2;
    973             L2 = 0.6;
    974             L3 = 1.2;
    975         } else {
    976             L1 = 0.25;
    977             L2 = 1.4;
    978             L3 = 2.4;
    979         }
    980 
    981         // Calculate Initial QP if it has not been specified
    982         if (flBpp <= L1)
    983             psPicParams->sInParams.SeInitQP = 31;
    984         else {
    985             if (flBpp <= L2)
    986                 psPicParams->sInParams.SeInitQP = 25;
    987             else
    988                 psPicParams->sInParams.SeInitQP = (flBpp <= L3) ? 20 : 10;
    989         }
    990 
    991         psPicParams->sInParams.MinQPVal = 3;
    992 
    993         break;
    994 
    995     default:
    996         /* the NO RC cases will fall here */
    997         break;
    998     }
    999 
   1000     // Set up Input Parameters that are mode dependent
   1001     switch (psContext->eCodec) {
   1002     case IMG_CODEC_H264_NO_RC:
   1003     case IMG_CODEC_H263_NO_RC:
   1004     case IMG_CODEC_MPEG4_NO_RC:
   1005         return;
   1006 
   1007     case IMG_CODEC_H264_VCM:
   1008         psPicParams->Flags                              |= ISVCM_FLAGS | ISCBR_FLAGS;
   1009         /* drop through to CBR case */
   1010         /* for SD and above we can target 95% (122/128) of maximum bitrate */
   1011         if (psRCParams->VCMBitrateMargin) {
   1012             psPicParams->sInParams.VCMBitrateMargin = psRCParams->VCMBitrateMargin;
   1013         } else {
   1014             if (psContext->Height >= 480)
   1015                 psPicParams->sInParams.VCMBitrateMargin = 122;
   1016             else
   1017                 psPicParams->sInParams.VCMBitrateMargin = 115; /* for less and SD we target 90% (115/128) of maximum bitrate */
   1018             if (i32BufferSizeInFrames < 15)
   1019                 psPicParams->sInParams.VCMBitrateMargin -= 5;/* when we have a very small window size we reduce the target further to avoid too much skipping */
   1020         }
   1021         psPicParams->sInParams.ForceSkipMargin = 500;/* start skipping MBs when within 500 bits of slice or frame limit */
   1022 
   1023         // Set a scale factor to avoid overflows in maths
   1024         if (psRCParams->BitsPerSecond < 1000000) {      // 1 Mbits/s
   1025             psPicParams->sInParams.ScaleFactor = 0;
   1026         } else if (psRCParams->BitsPerSecond < 2000000) { // 2 Mbits/s
   1027             psPicParams->sInParams.ScaleFactor = 1;
   1028         } else if (psRCParams->BitsPerSecond < 4000000) { // 4 Mbits/s
   1029             psPicParams->sInParams.ScaleFactor = 2;
   1030         } else if (psRCParams->BitsPerSecond < 8000000) { // 8 Mbits/s
   1031             psPicParams->sInParams.ScaleFactor = 3;
   1032         } else {
   1033             psPicParams->sInParams.ScaleFactor = 4;
   1034         }
   1035 
   1036         psPicParams->sInParams.BufferSize = i32BufferSizeInFrames;
   1037         break;
   1038 
   1039     case IMG_CODEC_H264_CBR:
   1040         psPicParams->Flags                              |= ISCBR_FLAGS;
   1041         // ------------------- H264 CBR RC ------------------- //
   1042         // Initialize the parameters of fluid flow traffic model.
   1043         psPicParams->sInParams.BufferSize = psRCParams->BufferSize;
   1044 
   1045         // HRD consideration - These values are used by H.264 reference code.
   1046         if (psRCParams->BitsPerSecond < 1000000) {      // 1 Mbits/s
   1047             psPicParams->sInParams.ScaleFactor = 0;
   1048         } else if (psRCParams->BitsPerSecond < 2000000) { // 2 Mbits/s
   1049             psPicParams->sInParams.ScaleFactor = 1;
   1050         } else if (psRCParams->BitsPerSecond < 4000000) { // 4 Mbits/s
   1051             psPicParams->sInParams.ScaleFactor = 2;
   1052         } else if (psRCParams->BitsPerSecond < 8000000) { // 8 Mbits/s
   1053             psPicParams->sInParams.ScaleFactor = 3;
   1054         } else {
   1055             psPicParams->sInParams.ScaleFactor = 4;
   1056         }
   1057         break;
   1058 
   1059     case IMG_CODEC_MPEG4_CBR:
   1060     case IMG_CODEC_H263_CBR:
   1061         psPicParams->Flags                                      |= ISCBR_FLAGS;
   1062 
   1063         flBpp  = 256 * (psRCParams->BitsPerSecond / psContext->Width);
   1064         flBpp /= (psContext->Height * psRCParams->FrameRate);
   1065 
   1066         if ((psPicParams->sInParams.MBPerFrm > 1024 && flBpp < 16) || (psPicParams->sInParams.MBPerFrm <= 1024 && flBpp < 24))
   1067             psPicParams->sInParams.HalfFrameRate = 1;
   1068         else
   1069             psPicParams->sInParams.HalfFrameRate = 0;
   1070 
   1071         if (psPicParams->sInParams.HalfFrameRate >= 1) {
   1072             psPicParams->sInParams.SeInitQP = 31;
   1073             psPicParams->sInParams.AvQPVal = 31;
   1074             psPicParams->sInParams.MyInitQP = 31;
   1075         }
   1076 
   1077         if (psRCParams->BitsPerSecond <= 384000)
   1078             psPicParams->sInParams.BufferSize = ((psRCParams->BitsPerSecond * 5) >> 1);
   1079         else
   1080             psPicParams->sInParams.BufferSize = psRCParams->BitsPerSecond * 4;
   1081         break;
   1082 
   1083     case IMG_CODEC_MPEG4_VBR:
   1084     case IMG_CODEC_H263_VBR:
   1085     case IMG_CODEC_H264_VBR:
   1086         psPicParams->Flags                              |= ISVBR_FLAGS;
   1087 
   1088         psPicParams->sInParams.MBPerBU  = psPicParams->sInParams.MBPerFrm;
   1089         psPicParams->sInParams.BUPerFrm = 1;
   1090 
   1091         // Initialize the parameters of fluid flow traffic model.
   1092         psPicParams->sInParams.BufferSize       = ((5 * psRCParams->BitsPerSecond) >> 1);
   1093 
   1094         // These scale factor are used only for rate control to avoid overflow
   1095         // in fixed-point calculation these scale factors are decided by bit rate
   1096         if (psRCParams->BitsPerSecond < 640000) {
   1097             psPicParams->sInParams.ScaleFactor  = 2;                                            // related to complexity
   1098         } else if (psRCParams->BitsPerSecond < 2000000) {
   1099             psPicParams->sInParams.ScaleFactor  = 4;
   1100         } else {
   1101             psPicParams->sInParams.ScaleFactor  = 6;
   1102         }
   1103         break;
   1104     default:
   1105         break;
   1106     }
   1107 
   1108     psPicParams->sInParams.MyInitQP             = psPicParams->sInParams.SeInitQP;
   1109     psPicParams->sInParams.InitialDelay = psRCParams->InitialDelay;
   1110     psPicParams->sInParams.InitialLevel = psRCParams->InitialLevel;
   1111     psRCParams->InitialQp                               = psPicParams->sInParams.SeInitQP;
   1112 }
   1113 
   1114 
   1115 
   1116 static void lnc__setup_qpvalue_h264(
   1117     MTX_CURRENT_IN_PARAMS * psCurrent,
   1118     IMG_BYTE bySliceQP)
   1119 {
   1120     /* H.264 QP scaling tables */
   1121     IMG_BYTE HOST_PVR_QP_SCALE_CR[52] = {
   1122         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
   1123         12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
   1124         28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36, 37, 37,
   1125         37, 38, 38, 38, 39, 39, 39, 39
   1126     };
   1127 
   1128     psCurrent->bySliceQP = bySliceQP;
   1129     psCurrent->bySliceQPC = HOST_PVR_QP_SCALE_CR[psCurrent->bySliceQP];
   1130 }
   1131 
   1132 
   1133 static void lnc__setup_qpvalues_mpeg4(
   1134     MTX_CURRENT_IN_PARAMS * psCurrent,
   1135     IMG_BYTE bySliceQP)
   1136 {
   1137     psCurrent->bySliceQP =      bySliceQP;
   1138 }
   1139 
   1140 
   1141 static void lnc__setup_slice_row_params(
   1142     context_ENC_p ctx,
   1143     IMG_BOOL IsIntra,
   1144     IMG_UINT16 CurrentRowY,
   1145     IMG_INT16 SliceStartRowY,
   1146     IMG_INT16 SliceHeight,
   1147     IMG_BOOL VectorsValid,
   1148     int bySliceQP)
   1149 {
   1150     /* Note: CurrentRowY and SliceStartRowY are now in pixels (not MacroBlocks)
   1151      * - saves needless multiplications and divisions
   1152      */
   1153     IMG_INT16   Pos, YPos, srcY;
   1154     MTX_CURRENT_IN_PARAMS *psCurrent;
   1155     lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
   1156     IMG_UINT16  tmp;
   1157 
   1158     if (IsIntra && cmdbuf->topaz_in_params_I_p == NULL) {
   1159         VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_in_params_I, &cmdbuf->topaz_in_params_I_p);
   1160         if (vaStatus != VA_STATUS_SUCCESS) {
   1161             drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
   1162             return;
   1163         }
   1164     }
   1165 
   1166     if ((!IsIntra) && cmdbuf->topaz_in_params_P_p == NULL) {
   1167         VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_in_params_P, &cmdbuf->topaz_in_params_P_p);
   1168         if (vaStatus != VA_STATUS_SUCCESS) {
   1169             drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
   1170             return;
   1171         }
   1172     }
   1173     if (IsIntra)
   1174         psCurrent = (MTX_CURRENT_IN_PARAMS*)(cmdbuf->topaz_in_params_I_p + ctx->in_params_ofs);
   1175     else
   1176         psCurrent = (MTX_CURRENT_IN_PARAMS*)(cmdbuf->topaz_in_params_P_p + ctx->in_params_ofs);
   1177 
   1178     psCurrent += (CurrentRowY  * (ctx->Width) / 256);
   1179 
   1180     if ((YPos = srcY = CurrentRowY - MVEA_LRB_TOP_OFFSET) < 0)
   1181         srcY = 0;
   1182     else if (YPos > ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16)
   1183         srcY = ctx->HeightMinusLRBSearchHeight;
   1184 
   1185     tmp = (CurrentRowY != SliceStartRowY);
   1186 
   1187     for (Pos = 0; Pos < (int)ctx->Width; Pos += 16, psCurrent++) {
   1188         memset(psCurrent, 0, sizeof(MTX_CURRENT_IN_PARAMS));
   1189         psCurrent->MVValid = 0;
   1190         psCurrent->ParamsValid = 0;
   1191 
   1192         /* Setup the parameters and motion vectors */
   1193         if (tmp) {
   1194             psCurrent->MVValid = 66;
   1195             psCurrent->ParamsValid |= PARAMS_ABOVE_VALID;
   1196 
   1197             if (Pos + 16 < (int)ctx->Width) {
   1198                 psCurrent->ParamsValid |= PARAMS_ABOVER_VALID;
   1199                 psCurrent->MVValid |= 4; /* (1<<2) */
   1200             }
   1201 
   1202             if (Pos > 0 && (Pos < (int)ctx->Width)) {
   1203                 psCurrent->ParamsValid |= PARAMS_ABOVEL_VALID;
   1204                 psCurrent->MVValid |= 1; /* (1<<0) */
   1205             }
   1206         }
   1207         if ((Pos == 0) && (CurrentRowY == SliceStartRowY)) {
   1208             psCurrent->ParamsValid |= MB_START_OF_SLICE;/* OPTI? */
   1209         }
   1210         /* Have to fill in the right hand row of 4x4 vectors into the the left block */
   1211         if (Pos) {
   1212             psCurrent->MVValid |= 72; /* (1<<3)+(1<<6) */
   1213             psCurrent->ParamsValid |= 8; /* (1<<3) */
   1214         }
   1215         if (Pos == (int)(ctx->Width - 16)) {
   1216             /* indicate the last MB in a row */
   1217             psCurrent->ParamsValid |= MB_END_OF_ROW;
   1218             /* are we the last mb in the slice? */
   1219             if (YPos == (SliceStartRowY + SliceHeight - (MVEA_LRB_TOP_OFFSET + 16))) {
   1220                 psCurrent->ParamsValid |= MB_END_OF_SLICE;
   1221                 if (YPos == ctx->HeightMinus16MinusLRBTopOffset) {
   1222                     psCurrent->ParamsValid |= MB_END_OF_PICTURE;
   1223                 }
   1224             }
   1225         }
   1226         /* And now the below block
   1227          * should do some kind of check to see if we are the first inter block,
   1228          * as otherwise the vectors will be invalid!
   1229          */
   1230         if (VectorsValid) {
   1231             if (YPos < ctx->HeightMinus16MinusLRBTopOffset) {
   1232                 psCurrent->MVValid |= 16; /* (1<<4) */
   1233 
   1234                 if (YPos < ctx->HeightMinus32MinusLRBTopOffset) {
   1235                     psCurrent->MVValid |= 32; /* (1<<5) */
   1236                 }
   1237             }
   1238         }
   1239 
   1240         /* Set up IPEMin and Max for coordinate X in the search reference region */
   1241         /* And set up flags in SPEMax when needed */
   1242         if (Pos <= 48) {
   1243             psCurrent->IPEMin[0] = 48 - Pos;
   1244             psCurrent->RealEdge |= SPE_EDGE_LEFT;
   1245         } else {
   1246             psCurrent->IPEMin[0] = 3;
   1247         }
   1248 
   1249         if ((Pos + 48 + 16) > (int)ctx->Width) {
   1250             psCurrent->IPEMax[0] = (47 + ctx->Width) - Pos; /* (112 - 1) - ((Pos + 48+16) - ctx->Width); */
   1251             psCurrent->RealEdge |= SPE_EDGE_RIGHT;
   1252         } else {
   1253             psCurrent->IPEMax[0] = 108; /* (112 - 1) - 3; */
   1254         }
   1255 
   1256         /* Set up IPEMin and Max for Y coordinate in the search reference region */
   1257         /* And set up flags in SPEMax when needed */
   1258         if (YPos <= 0) {
   1259             psCurrent->IPEMin[1] = 0;
   1260             psCurrent->RealEdge |= SPE_EDGE_TOP;
   1261         } else {
   1262             psCurrent->IPEMin[1] = 3;
   1263         }
   1264 
   1265         /* Max Y */
   1266         if (YPos > ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16) {
   1267             psCurrent->IPEMax[1] = MVEA_LRB_SEARCH_HEIGHT - 1;
   1268             psCurrent->RealEdge |= SPE_EDGE_BOTTOM;
   1269         } else {
   1270             psCurrent->IPEMax[1] = MVEA_LRB_SEARCH_HEIGHT - 4;
   1271         }
   1272 
   1273         psCurrent->CurBlockAddr = ((IMG_UINT8)(((YPos + MVEA_LRB_TOP_OFFSET) - srcY) / 16) << 4) | 0x3;
   1274 
   1275         /* Setup the control register values These will get setup and transferred to a different location within
   1276          * the macroblock parameter structure.  They are then read out of the esb by the mtx and used to control
   1277          * the hardware units
   1278          */
   1279         psCurrent->IPEControl = ctx->IPEControl;
   1280 
   1281         switch (ctx->eCodec) {
   1282         case IMG_CODEC_H263_NO_RC:
   1283         case IMG_CODEC_H263_VBR:
   1284         case IMG_CODEC_H263_CBR:
   1285             lnc__setup_qpvalues_mpeg4(psCurrent, bySliceQP);
   1286             psCurrent->JMCompControl = F_ENCODE(2, MVEA_CR_JMCOMP_MODE);
   1287             psCurrent->VLCControl = F_ENCODE(3, TOPAZ_VLC_CR_CODEC) |
   1288                                     F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
   1289             break;
   1290         case IMG_CODEC_MPEG4_NO_RC:
   1291         case IMG_CODEC_MPEG4_VBR:
   1292         case IMG_CODEC_MPEG4_CBR:
   1293             lnc__setup_qpvalues_mpeg4(psCurrent, bySliceQP);
   1294             psCurrent->JMCompControl = F_ENCODE(1, MVEA_CR_JMCOMP_MODE) |
   1295                                        F_ENCODE(1, MVEA_CR_JMCOMP_AC_ENABLE);
   1296             psCurrent->VLCControl = F_ENCODE(2, TOPAZ_VLC_CR_CODEC) |
   1297                                     F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
   1298             break;
   1299         default:
   1300         case IMG_CODEC_H264_NO_RC:
   1301         case IMG_CODEC_H264_VBR:
   1302         case IMG_CODEC_H264_CBR:
   1303         case IMG_CODEC_H264_VCM:
   1304             lnc__setup_qpvalue_h264(psCurrent, bySliceQP);
   1305             psCurrent->JMCompControl = F_ENCODE(0, MVEA_CR_JMCOMP_MODE);
   1306             psCurrent->VLCControl = F_ENCODE(1, TOPAZ_VLC_CR_CODEC) |
   1307                                     F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
   1308             break;
   1309         }
   1310     }
   1311 
   1312     psCurrent->RealEdge = 0;
   1313 
   1314 }
   1315 
   1316 void lnc_setup_slice_params(
   1317     context_ENC_p  ctx,
   1318     IMG_UINT16 YSliceStartPos,
   1319     IMG_UINT16 SliceHeight,
   1320     IMG_BOOL IsIntra,
   1321     IMG_BOOL  VectorsValid,
   1322     int bySliceQP)
   1323 {
   1324     IMG_UINT16 Rows, CurrentRowY;
   1325 
   1326     Rows = SliceHeight / 16;
   1327     CurrentRowY = YSliceStartPos;
   1328 
   1329     while (Rows) {
   1330         lnc__setup_slice_row_params(
   1331             ctx,
   1332             IsIntra,
   1333             CurrentRowY,
   1334             YSliceStartPos,
   1335             SliceHeight,
   1336             VectorsValid, bySliceQP);
   1337 
   1338         CurrentRowY += 16;
   1339         Rows--;
   1340     }
   1341 
   1342 }
   1343 
   1344 
   1345 
   1346 IMG_UINT32 lnc__send_encode_slice_params(
   1347     context_ENC_p ctx,
   1348     IMG_BOOL IsIntra,
   1349     IMG_UINT16 CurrentRow,
   1350     IMG_BOOL DeblockSlice,
   1351     IMG_UINT32 FrameNum,
   1352     IMG_UINT16 SliceHeight,
   1353     IMG_UINT16 CurrentSlice,
   1354     IMG_UINT32 MaxSliceSize)
   1355 {
   1356     SLICE_PARAMS *psSliceParams;
   1357     IMG_UINT16 RowOffset;
   1358 
   1359     psb_buffer_p psCoded;
   1360     object_surface_p ref_surface;
   1361     psb_buffer_p psRef;
   1362     lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
   1363 
   1364 
   1365     ref_surface = ctx->ref_surface;
   1366     psRef = &ctx->ref_surface->psb_surface->buf;
   1367     psCoded = ctx->coded_buf->psb_buffer;
   1368 
   1369     psSliceParams = (SLICE_PARAMS *)(cmdbuf->slice_params_p +
   1370                                      CurrentSlice * ((sizeof(SLICE_PARAMS) + 15) & 0xfff0));
   1371 
   1372     psSliceParams->SliceHeight = SliceHeight;
   1373     psSliceParams->SliceStartRowNum = CurrentRow / 16;
   1374 
   1375     /* We want multiple ones of these so we can submit multiple slices without having to wait for the next */
   1376     psSliceParams->CodedDataPos = 0;
   1377     psSliceParams->TotalCoded = 0;
   1378     psSliceParams->Flags = 0;
   1379 
   1380 #ifdef VA_EMULATOR
   1381     psSliceParams->RefYStride = ref_surface->psb_surface->stride;
   1382     psSliceParams->RefUVStride = ref_surface->psb_surface->stride;
   1383     psSliceParams->RefYRowStride =  ref_surface->psb_surface->stride * 16;
   1384     psSliceParams->RefUVRowStride = ref_surface->psb_surface->stride * 16 / 2;
   1385 #else
   1386     psSliceParams->RefYStride = ref_surface->height * 16;
   1387     psSliceParams->RefUVStride = ref_surface->height * 8;
   1388     psSliceParams->RefYRowStride =  psSliceParams->RefYStride;
   1389     psSliceParams->RefUVRowStride = psSliceParams->RefUVStride;
   1390 #endif
   1391 
   1392     psSliceParams->FCode = ctx->FCode;/* Not clear yet, This field is not appare in firmware doc */
   1393     RowOffset = CurrentRow - 32;
   1394     if (RowOffset <= 0)
   1395         RowOffset = 0;
   1396     if (RowOffset > (ctx->Height - 80))
   1397         RowOffset = (ctx->Height - 80);
   1398 
   1399     psSliceParams->MaxSliceSize = MaxSliceSize;
   1400     psSliceParams->NumAirMBs = ctx->num_air_mbs;
   1401     /* DDKv145: 3 lsb of threshold used as spacing between AIR MBs */
   1402     psSliceParams->AirThreshold = ctx->air_threshold + (FrameNum & 3) + 2;
   1403 
   1404     if (ctx->autotune_air_flag)
   1405         psSliceParams->Flags |= AUTOTUNE_AIR;
   1406 
   1407     if (!IsIntra) {
   1408         psSliceParams->Flags |= ISINTER_FLAGS;
   1409     }
   1410     if (DeblockSlice) {
   1411         psSliceParams->Flags |= DEBLOCK_FRAME;
   1412     }
   1413     switch (ctx->eCodec) {
   1414     case IMG_CODEC_H263_NO_RC:
   1415     case IMG_CODEC_H263_VBR:
   1416     case IMG_CODEC_H263_CBR:
   1417         psSliceParams->Flags |= ISH263_FLAGS;
   1418         break;
   1419     case IMG_CODEC_MPEG4_NO_RC:
   1420     case IMG_CODEC_MPEG4_VBR:
   1421     case IMG_CODEC_MPEG4_CBR:
   1422         psSliceParams->Flags |= ISMPEG4_FLAGS;
   1423         break;
   1424     case IMG_CODEC_H264_NO_RC:
   1425     case IMG_CODEC_H264_VBR:
   1426     case IMG_CODEC_H264_CBR:
   1427     case IMG_CODEC_H264_VCM:
   1428         psSliceParams->Flags |= ISH264_FLAGS;
   1429         break;
   1430     default:
   1431         psSliceParams->Flags |= ISH264_FLAGS;
   1432         drv_debug_msg(VIDEO_DEBUG_ERROR, "No format specified defaulting to h.264\n");
   1433         break;
   1434     }
   1435     /* we should also setup the interleaving requirements based on the source format */
   1436     if (ctx->eFormat != IMG_CODEC_PL12)
   1437         psSliceParams->Flags |= INTERLEAVE_TARGET;
   1438 
   1439     cmdbuf = ctx->obj_context->lnc_cmdbuf;
   1440 
   1441     RELOC_SLICE_PARAMS(&(psSliceParams->RefYBase), 16 * RowOffset, psRef);
   1442     RELOC_SLICE_PARAMS(&(psSliceParams->RefUVBase),
   1443                        ref_surface->psb_surface->stride * ref_surface->height + (RowOffset * 16 / 2),
   1444                        psRef);
   1445     RELOC_SLICE_PARAMS(&(psSliceParams->CodedData), 0, psCoded);
   1446 
   1447     lnc_cmdbuf_insert_command(cmdbuf, MTX_CMDID_ENCODE_SLICE, 2, (CurrentSlice << 2) | (IsIntra & 0x3));
   1448     RELOC_CMDBUF(cmdbuf->cmd_idx++,
   1449                  CurrentSlice *((sizeof(SLICE_PARAMS) + 15) & 0xfff0),
   1450                  &cmdbuf->slice_params);
   1451 
   1452     return 0;
   1453 }
   1454 
   1455 
   1456 
   1457 /*
   1458  * Function Name      : Reset_EncoderParams
   1459  * Description        : Reset Above & Below Params at the Start of Intra frame
   1460  */
   1461 void lnc_reset_encoder_params(context_ENC_p ctx)
   1462 {
   1463     unsigned char *Add_Below, *Add_Above;
   1464     lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
   1465 
   1466     /* all frames share the same Topaz param, in_param/aboveparam/bellow
   1467      * map it only when necessary
   1468      */
   1469     if (cmdbuf->topaz_above_bellow_params_p == NULL) {
   1470         VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_above_bellow_params, &cmdbuf->topaz_above_bellow_params_p);
   1471         if (vaStatus != VA_STATUS_SUCCESS) {
   1472             drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
   1473             return;
   1474         }
   1475     }
   1476 
   1477     Add_Below = cmdbuf->topaz_above_bellow_params_p + ctx->bellow_params_ofs;
   1478     memset(Add_Below, 0, ctx->bellow_params_size);
   1479 
   1480     Add_Above = cmdbuf->topaz_above_bellow_params_p + ctx->above_params_ofs;
   1481     memset(Add_Above, 0, ctx->above_params_size);
   1482 }
   1483