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