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