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@intel.com>
27  *    Shengquan Yuan  <shengquan.yuan@intel.com>
28  *    Binglin Chen <binglin.chen@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 
lnc__alloc_context_buffer(context_ENC_p ctx)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 
lnc__get_ipe_control(enum drm_lnc_topaz_codec eEncodingFormat)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 
lnc_DestroyContext(object_context_p obj_context)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 
lnc_CreateContext(object_context_p obj_context,object_config_p obj_config)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 
lnc_BeginPicture(context_ENC_p ctx)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 
lnc_RenderPictureParameter(context_ENC_p ctx)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 
lnc__PatchBitsConsumedInRCParam(context_ENC_p ctx)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 
lnc_RedoRenderPictureSkippedFrame(context_ENC_p ctx)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 
lnc_SetupRCParam(context_ENC_p ctx)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 
lnc_UpdateRCParam(context_ENC_p ctx)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 
lnc_PatchRCMode(context_ENC_p ctx)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 
lnc_EndPicture(context_ENC_p ctx)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 
lnc__setup_busize(context_ENC_p ctx)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  ************************************************************************************/
lnc__setup_rcdata(context_ENC_p psContext,PIC_PARAMS * psPicParams,IMG_RC_PARAMS * psRCParams)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 
lnc__update_rcdata(context_ENC_p psContext,PIC_PARAMS * psPicParams,IMG_RC_PARAMS * psRCParams)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 
lnc__setup_qpvalue_h264(MTX_CURRENT_IN_PARAMS * psCurrent,IMG_BYTE bySliceQP)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 
lnc__setup_qpvalues_mpeg4(MTX_CURRENT_IN_PARAMS * psCurrent,IMG_BYTE bySliceQP)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 
lnc__setup_slice_row_params(context_ENC_p ctx,IMG_BOOL IsIntra,IMG_UINT16 CurrentRowY,IMG_INT16 SliceStartRowY,IMG_INT16 SliceHeight,IMG_BOOL VectorsValid,int bySliceQP)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 
lnc_setup_slice_params(context_ENC_p ctx,IMG_UINT16 YSliceStartPos,IMG_UINT16 SliceHeight,IMG_BOOL IsIntra,IMG_BOOL VectorsValid,int bySliceQP)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 
lnc__send_encode_slice_params(context_ENC_p ctx,IMG_BOOL IsIntra,IMG_UINT16 CurrentRow,IMG_BOOL DeblockSlice,IMG_UINT32 FrameNum,IMG_UINT16 SliceHeight,IMG_UINT16 CurrentSlice,IMG_UINT32 MaxSliceSize)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  */
lnc_reset_encoder_params(context_ENC_p ctx)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