1 /* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * Copyright (c) Imagination Technologies Limited, UK 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: 26 * Elaine Wang <elaine.wang (at) intel.com> 27 * Zeng Li <zeng.li (at) intel.com> 28 * Edward Lin <edward.lin (at) intel.com> 29 * 30 */ 31 32 #include <errno.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <stdint.h> 36 #include <string.h> 37 #include <limits.h> 38 39 #include "hwdefs/coreflags.h" 40 #include "hwdefs/topaz_vlc_regs.h" 41 #include "hwdefs/topaz_db_regs.h" 42 43 #include "va/va_enc_h264.h" 44 45 #include "psb_def.h" 46 #include "psb_drv_debug.h" 47 #include "psb_surface.h" 48 #include "tng_cmdbuf.h" 49 #include "tng_hostcode.h" 50 #include "tng_hostheader.h" 51 #include "tng_picmgmt.h" 52 #include "tng_slotorder.h" 53 #include "tng_hostair.h" 54 #include "tng_H264ES.h" 55 #ifdef _TOPAZHP_PDUMP_ 56 #include "tng_trace.h" 57 #endif 58 59 #define TOPAZ_H264_MAX_BITRATE 135000000 60 61 #define INIT_CONTEXT_H264ES context_ENC_p ctx = (context_ENC_p) obj_context->format_data 62 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id )) 63 #define BUFFER(id) ((object_buffer_p) object_heap_lookup( &ctx->obj_context->driver_data->buffer_heap, id )) 64 65 static VAStatus tng__H264ES_init_profile( 66 object_context_p obj_context, 67 object_config_p obj_config) 68 { 69 VAStatus vaStatus = VA_STATUS_SUCCESS; 70 context_ENC_p ctx; 71 ctx = (context_ENC_p) obj_context->format_data; 72 switch (obj_config->profile) { 73 case VAProfileH264Baseline: 74 case VAProfileH264ConstrainedBaseline: 75 ctx->ui8ProfileIdc = H264ES_PROFILE_BASELINE; 76 break; 77 case VAProfileH264Main: 78 ctx->ui8ProfileIdc = H264ES_PROFILE_MAIN; 79 break; 80 case VAProfileH264High: 81 ctx->ui8ProfileIdc = H264ES_PROFILE_HIGH; 82 break; 83 case VAProfileH264StereoHigh: 84 ctx->ui8ProfileIdc = H264ES_PROFILE_HIGH; 85 ctx->bEnableMVC = 1; 86 ctx->ui16MVCViewIdx = 0; 87 break; 88 default: 89 ctx->ui8ProfileIdc = H264ES_PROFILE_BASELINE; 90 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; 91 break; 92 } 93 drv_debug_msg(VIDEO_DEBUG_GENERAL, 94 "%s: obj_config->profile = %dctx->eStandard = %d, ctx->bEnableMVC = %d\n", 95 __FUNCTION__, obj_config->profile, ctx->eStandard, ctx->bEnableMVC); 96 return vaStatus; 97 } 98 99 static VAStatus tng__H264ES_get_codec_type( 100 object_context_p obj_context, 101 object_config_p __maybe_unused obj_config) 102 { 103 VAStatus vaStatus = VA_STATUS_SUCCESS; 104 context_ENC_p ctx = (context_ENC_p) obj_context->format_data; 105 IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); 106 107 ctx->eCodec = IMG_CODEC_NUM; 108 109 if (ctx->bEnableMVC) { 110 switch (psRCParams->eRCMode) { 111 case IMG_RCMODE_NONE: 112 ctx->eCodec = IMG_CODEC_H264MVC_NO_RC; 113 break; 114 case IMG_RCMODE_CBR: 115 ctx->eCodec = IMG_CODEC_H264MVC_CBR; 116 break; 117 case IMG_RCMODE_VBR: 118 ctx->eCodec = IMG_CODEC_H264MVC_VBR; 119 break; 120 default: 121 drv_debug_msg(VIDEO_DEBUG_ERROR, "RC mode MVC\n"); 122 break; 123 } 124 } else { 125 switch (psRCParams->eRCMode) { 126 case IMG_RCMODE_NONE: 127 ctx->eCodec = IMG_CODEC_H264_NO_RC; 128 break; 129 case IMG_RCMODE_CBR: 130 ctx->eCodec = IMG_CODEC_H264_CBR; 131 break; 132 case IMG_RCMODE_VBR: 133 ctx->eCodec = IMG_CODEC_H264_VBR; 134 break; 135 case IMG_RCMODE_VCM: 136 ctx->eCodec = IMG_CODEC_H264_VCM; 137 break; 138 default: 139 drv_debug_msg(VIDEO_DEBUG_ERROR, "RC mode\n"); 140 break; 141 } 142 } 143 return vaStatus; 144 } 145 146 static VAStatus tng__H264ES_init_format_mode( 147 object_context_p obj_context, 148 object_config_p __maybe_unused obj_config) 149 { 150 VAStatus vaStatus = VA_STATUS_SUCCESS; 151 context_ENC_p ctx = (context_ENC_p) obj_context->format_data; 152 153 ctx->bIsInterlaced = IMG_FALSE; 154 ctx->bIsInterleaved = IMG_FALSE; 155 ctx->ui16PictureHeight = ctx->ui16FrameHeight; 156 ctx->eCodec = IMG_CODEC_H264_NO_RC; 157 return vaStatus; 158 } 159 160 static void tng__H264ES_init_context(object_context_p obj_context, 161 object_config_p __maybe_unused obj_config) 162 { 163 context_ENC_p ctx = (context_ENC_p) obj_context->format_data; 164 //This parameter need not be exposed 165 ctx->ui8InterIntraIndex = 3; 166 ctx->ui8CodedSkippedIndex = 3; 167 ctx->bEnableHostQP = IMG_FALSE; 168 ctx->uMaxChunks = 0xA0; 169 ctx->uChunksPerMb = 0x40; 170 ctx->uPriorityChunks = (0xA0 - 0x60); 171 ctx->ui32FCode = 4; 172 ctx->iFineYSearchSize = 2; 173 174 //This parameter need not be exposed 175 //host to control the encoding process 176 ctx->bEnableInpCtrl = IMG_FALSE; 177 ctx->bEnableHostBias = IMG_FALSE; 178 //By default false Newly Added 179 ctx->bEnableCumulativeBiases = IMG_FALSE; 180 181 //Weighted Prediction is not supported in TopazHP Version 3.0 182 ctx->bWeightedPrediction = IMG_FALSE; 183 ctx->ui8VPWeightedImplicitBiPred = 0; 184 ctx->bInsertHRDParams = IMG_FALSE; 185 ctx->bArbitrarySO = IMG_FALSE; 186 ctx->ui32BasicUnit = 0; 187 ctx->idr_force_flag = 0; 188 ctx->bVPAdaptiveRoundingDisable = IMG_FALSE; 189 } 190 191 static VAStatus tng__H264ES_process_misc_framerate_param(context_ENC_p ctx, object_buffer_p obj_buffer) 192 { 193 VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data; 194 VAEncMiscParameterFrameRate *psMiscFrameRateParam; 195 IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); 196 197 ASSERT(obj_buffer->type == VAEncMiscParameterTypeFrameRate); 198 ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterFrameRate)); 199 200 psMiscFrameRateParam = (VAEncMiscParameterFrameRate *)(pBuffer->data); 201 202 if (psMiscFrameRateParam == NULL) 203 return VA_STATUS_ERROR_INVALID_BUFFER; 204 205 if (psMiscFrameRateParam->framerate < 1 || psMiscFrameRateParam->framerate > 65535) 206 return VA_STATUS_ERROR_INVALID_PARAMETER; 207 208 209 if (psRCParams->ui32FrameRate == 0) 210 psRCParams->ui32FrameRate = psMiscFrameRateParam->framerate; 211 else { 212 if(psMiscFrameRateParam->framerate != psRCParams->ui32FrameRate){ 213 if (psMiscFrameRateParam->framerate > psRCParams->ui32FrameRate) 214 psRCParams->ui32BitsPerSecond /= (float)psMiscFrameRateParam->framerate / psRCParams->ui32FrameRate; 215 else 216 psRCParams->ui32BitsPerSecond *= (float)psRCParams->ui32FrameRate / psMiscFrameRateParam->framerate; 217 psRCParams->ui32FrameRate = psMiscFrameRateParam->framerate; 218 ctx->rc_update_flag |= RC_MASK_frame_rate; 219 } 220 } 221 222 return VA_STATUS_SUCCESS; 223 } 224 225 static VAStatus tng__H264ES_process_misc_ratecontrol_param(context_ENC_p ctx, object_buffer_p obj_buffer) 226 { 227 IMG_INT32 ui32BitsPerFrame; 228 VAEncMiscParameterRateControl *psMiscRcParams; 229 IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); 230 VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data; 231 unsigned int max_bps; 232 233 ASSERT(obj_buffer->type == VAEncMiscParameterTypeRateControl); 234 ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterRateControl)); 235 psMiscRcParams = (VAEncMiscParameterRateControl *)pBuffer->data; 236 237 #ifdef _TOPAZHP_PDUMP_ 238 tng_H264ES_trace_misc_rc_params(psMiscRcParams); 239 #endif 240 241 drv_debug_msg(VIDEO_DEBUG_GENERAL, 242 "%s psRCParams->ui32BitsPerSecond = %d, psMiscRcParams->bits_per_second = %d \n", 243 __FUNCTION__, psRCParams->ui32BitsPerSecond, psMiscRcParams->bits_per_second); 244 245 if (psMiscRcParams->bits_per_second > TOPAZ_H264_MAX_BITRATE) { 246 drv_debug_msg(VIDEO_DEBUG_GENERAL, 247 "%s: bits_per_second(%d) exceeds the maximum bitrate, set it with %d\n", 248 __FUNCTION__, psMiscRcParams->bits_per_second, TOPAZ_H264_MAX_BITRATE); 249 psMiscRcParams->bits_per_second = TOPAZ_H264_MAX_BITRATE; 250 } 251 252 if ((psRCParams->ui32BitsPerSecond != psMiscRcParams->bits_per_second) && 253 psMiscRcParams->bits_per_second != 0) { 254 psRCParams->ui32BitsPerSecond = psMiscRcParams->bits_per_second; 255 ctx->rc_update_flag |= RC_MASK_bits_per_second; 256 } 257 258 drv_debug_msg(VIDEO_DEBUG_GENERAL, 259 "%s: rate control changed from %d to %d\n", __FUNCTION__, 260 psRCParams->ui32BitsPerSecond, psMiscRcParams->bits_per_second); 261 262 if (psMiscRcParams->rc_flags.value != 0) { 263 if (psMiscRcParams->rc_flags.bits.disable_bit_stuffing) 264 ctx->sRCParams.bDisableBitStuffing = IMG_TRUE; 265 drv_debug_msg(VIDEO_DEBUG_GENERAL, "bDisableBitStuffing is %d\n", 266 ctx->sRCParams.bDisableBitStuffing); 267 } 268 269 if (psMiscRcParams->window_size > 2000) { 270 drv_debug_msg(VIDEO_DEBUG_ERROR, "window_size is too much!\n"); 271 return VA_STATUS_ERROR_INVALID_PARAMETER; 272 } 273 274 if (psMiscRcParams->window_size != 0) 275 ctx->uiCbrBufferTenths = psMiscRcParams->window_size / 100; 276 277 if (psRCParams->ui32FrameRate == 0) 278 psRCParams->ui32FrameRate = 30; 279 280 /* According to Table A-1 Level limits, if resolution is bigger than 625SD, 281 min compression ratio is 4, otherwise min compression ratio is 2 */ 282 if (psRCParams->ui32BitsPerSecond == 0) { 283 max_bps = (ctx->obj_context->picture_width * ctx->obj_context->picture_height * 3 / 2 ) * 8 * psRCParams->ui32FrameRate; 284 if (ctx->ui16SourceWidth > 720) 285 max_bps /= 4; 286 else 287 max_bps /= 2; 288 psRCParams->ui32BitsPerSecond = max_bps; 289 } 290 291 if (ctx->uiCbrBufferTenths) { 292 psRCParams->ui32BufferSize = (IMG_UINT32)(psRCParams->ui32BitsPerSecond * ctx->uiCbrBufferTenths / 10.0); 293 } else { 294 if (psRCParams->ui32BitsPerSecond < 256000) 295 psRCParams->ui32BufferSize = ((9 * psRCParams->ui32BitsPerSecond) >> 1); 296 else 297 psRCParams->ui32BufferSize = ((5 * psRCParams->ui32BitsPerSecond) >> 1); 298 } 299 300 drv_debug_msg(VIDEO_DEBUG_GENERAL, 301 "%s ctx->uiCbrBufferTenths = %d, psRCParams->ui32BufferSize = %d\n", 302 __FUNCTION__, ctx->uiCbrBufferTenths, psRCParams->ui32BufferSize); 303 drv_debug_msg(VIDEO_DEBUG_GENERAL, 304 "%s psRCParams->ui32BitsPerSecond = %d, psMiscRcParams->bits_per_second = %d\n", 305 __FUNCTION__, psRCParams->ui32BitsPerSecond, psMiscRcParams->bits_per_second); 306 307 //psRCParams->ui32BUSize = psMiscRcParams->basic_unit_size; 308 psRCParams->i32InitialDelay = (13 * psRCParams->ui32BufferSize) >> 4; 309 psRCParams->i32InitialLevel = (3 * psRCParams->ui32BufferSize) >> 4; 310 311 ui32BitsPerFrame = psRCParams->ui32BitsPerSecond / psRCParams->ui32FrameRate; 312 /* in order to minimise mismatches between firmware and external world InitialLevel should be a multiple of ui32BitsPerFrame */ 313 psRCParams->i32InitialLevel = ((psRCParams->i32InitialLevel + ui32BitsPerFrame / 2) / ui32BitsPerFrame) * ui32BitsPerFrame; 314 psRCParams->i32InitialLevel = tng__max(psRCParams->i32InitialLevel, ui32BitsPerFrame); 315 psRCParams->i32InitialDelay = psRCParams->ui32BufferSize - psRCParams->i32InitialLevel; 316 317 //free(psMiscRcParams); 318 if (psMiscRcParams->initial_qp > 51 || 319 psMiscRcParams->min_qp > 51 || 320 psMiscRcParams->max_qp > 51) { 321 drv_debug_msg(VIDEO_DEBUG_ERROR, 322 "%s: Initial_qp(%d) min_qp(%d) max_qp(%d) invalid.\nQP shouldn't be larger than 51 for H264\n", 323 __FUNCTION__, psMiscRcParams->initial_qp, psMiscRcParams->min_qp, psMiscRcParams->max_qp); 324 return VA_STATUS_ERROR_INVALID_PARAMETER; 325 } 326 327 if ((psRCParams->ui32InitialQp != psMiscRcParams->initial_qp) && 328 (psMiscRcParams->initial_qp != 0)) { 329 drv_debug_msg(VIDEO_DEBUG_GENERAL, 330 "%s: initial_qp updated from %d to %d\n", 331 __FUNCTION__, psRCParams->ui32InitialQp, psMiscRcParams->initial_qp); 332 ctx->rc_update_flag |= RC_MASK_initial_qp; 333 psRCParams->ui32InitialQp = psMiscRcParams->initial_qp; 334 } 335 336 if ((psRCParams->iMinQP != psMiscRcParams->min_qp) && 337 (psMiscRcParams->min_qp != 0)) { 338 drv_debug_msg(VIDEO_DEBUG_GENERAL, 339 "%s: min_qp updated from %d to %d\n", 340 __FUNCTION__, psRCParams->iMinQP, psMiscRcParams->min_qp); 341 ctx->rc_update_flag |= RC_MASK_min_qp; 342 psRCParams->iMinQP = psMiscRcParams->min_qp; 343 } 344 345 if ((ctx->max_qp != psMiscRcParams->max_qp) && 346 (psMiscRcParams->max_qp != 0)) { 347 drv_debug_msg(VIDEO_DEBUG_GENERAL, 348 "%s: max_qp updated from %d to %d\n", 349 __FUNCTION__, ctx->max_qp, psMiscRcParams->max_qp); 350 ctx->rc_update_flag |= RC_MASK_max_qp; 351 ctx->max_qp = psMiscRcParams->max_qp; 352 } 353 354 return VA_STATUS_SUCCESS; 355 } 356 357 static VAStatus tng__H264ES_process_misc_hrd_param(context_ENC_p ctx, object_buffer_p obj_buffer) 358 { 359 VAStatus vaStatus = VA_STATUS_SUCCESS; 360 VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data; 361 VAEncMiscParameterHRD *psMiscHrdParams = NULL; 362 IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); 363 ASSERT(obj_buffer->type == VAEncMiscParameterTypeHRD); 364 ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterHRD)); 365 psMiscHrdParams = (VAEncMiscParameterHRD *)pBuffer->data; 366 367 if (psMiscHrdParams->buffer_size == 0 368 || psMiscHrdParams->initial_buffer_fullness == 0) { 369 drv_debug_msg(VIDEO_DEBUG_ERROR, "Find zero value for buffer_size " 370 "and initial_buffer_fullness.\n"); 371 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 372 return vaStatus; 373 } 374 375 if (ctx->initial_buffer_fullness > ctx->buffer_size) { 376 drv_debug_msg(VIDEO_DEBUG_ERROR, "initial_buffer_fullnessi(%d) shouldn't be" 377 " larger that buffer_size(%d)!\n", 378 psMiscHrdParams->initial_buffer_fullness, 379 psMiscHrdParams->buffer_size); 380 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 381 return vaStatus; 382 } 383 384 if (!psRCParams->bRCEnable) { 385 drv_debug_msg(VIDEO_DEBUG_ERROR, "Only when rate control is enabled," 386 " VAEncMiscParameterTypeHRD will take effect.\n"); 387 vaStatus = VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; 388 return vaStatus; 389 } 390 391 ctx->buffer_size = psMiscHrdParams->buffer_size; 392 ctx->initial_buffer_fullness = psMiscHrdParams->initial_buffer_fullness; 393 ctx->bInsertHRDParams = IMG_TRUE; 394 drv_debug_msg(VIDEO_DEBUG_GENERAL, "hrd param buffer_size set to %d " 395 "initial buffer fullness set to %d\n", 396 ctx->buffer_size, ctx->initial_buffer_fullness); 397 398 return VA_STATUS_SUCCESS; 399 } 400 401 //APP_SetVideoParams 402 static VAStatus tng__H264ES_process_misc_air_param(context_ENC_p ctx, object_buffer_p obj_buffer) 403 { 404 VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data; 405 VAEncMiscParameterAIR *psMiscAirParams = NULL; 406 ADAPTIVE_INTRA_REFRESH_INFO_TYPE *psAIRInfo = &(ctx->sAirInfo); 407 IMG_UINT32 ui32MbNum; 408 ASSERT(obj_buffer->type == VAEncMiscParameterTypeAIR); 409 ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterAIR)); 410 411 psMiscAirParams = (VAEncMiscParameterAIR*)pBuffer->data; 412 ui32MbNum = (ctx->ui16PictureHeight * ctx->ui16Width) >> 8; 413 414 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: enable_AIR = %d, mb_num = %d, thresh_hold = %d, air_auto = %d\n", __FUNCTION__, 415 ctx->bEnableAIR, psMiscAirParams->air_num_mbs, psMiscAirParams->air_threshold, psMiscAirParams->air_auto); 416 417 ctx->bEnableAIR = 1; 418 ctx->bEnableInpCtrl = 1; 419 ctx->bEnableHostBias = 1; 420 ctx->ui8EnableSelStatsFlags |= ESF_FIRST_STAGE_STATS; 421 ctx->ui8EnableSelStatsFlags |= ESF_MP_BEST_MB_DECISION_STATS; 422 423 /*FIXME 424 if (psMiscAirParams->air_threshold == -1 && psMiscAirParams->air_num_mbs == 0) { 425 drv_debug_msg(VIDEO_DEBUG_ERROR, 426 "%s: ERROR: Cannot have both -AIRMBperFrame set to zero" 427 "AND and -AIRSADThreshold set to -1 (APP_SetVideoParams)\n", 428 __FUNCTION__); 429 return VA_STATUS_ERROR_INVALID_PARAMETER; 430 }*/ 431 432 if (psMiscAirParams->air_num_mbs > 65535) { 433 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: ERROR: air_num_mbs = %d should not bigger than 65536\n", 434 __FUNCTION__, psMiscAirParams->air_num_mbs); 435 return VA_STATUS_ERROR_INVALID_PARAMETER; 436 } 437 438 if (psMiscAirParams->air_num_mbs > ui32MbNum) 439 psMiscAirParams->air_num_mbs = ui32MbNum; 440 441 if (psMiscAirParams->air_threshold > 65535) { 442 drv_debug_msg(VIDEO_DEBUG_ERROR, 443 "%s: ERROR: air_threshold = %d should not bigger than 65536\n", 444 __FUNCTION__, psMiscAirParams->air_threshold); 445 return VA_STATUS_ERROR_INVALID_PARAMETER; 446 } 447 448 if (psMiscAirParams->air_auto) { 449 psAIRInfo->i32NumAIRSPerFrame = -1; 450 psAIRInfo->i32SAD_Threshold = -1; 451 psAIRInfo->i16AIRSkipCnt = -1; 452 } else { 453 psAIRInfo->i32NumAIRSPerFrame = psMiscAirParams->air_num_mbs; 454 psAIRInfo->i32SAD_Threshold = psMiscAirParams->air_threshold; 455 psAIRInfo->i16AIRSkipCnt = -1; 456 } 457 458 psAIRInfo->ui16AIRScanPos = 0; 459 460 drv_debug_msg(VIDEO_DEBUG_GENERAL, 461 "%s: air slice size changed to num_air_mbs %d " 462 "air_threshold %d, air_auto %d\n", __FUNCTION__, 463 psMiscAirParams->air_num_mbs, psMiscAirParams->air_threshold, 464 psMiscAirParams->air_auto); 465 466 if (psAIRInfo->pi8AIR_Table != NULL) 467 free(psAIRInfo->pi8AIR_Table); 468 tng_air_buf_create(ctx); 469 470 return VA_STATUS_SUCCESS; 471 } 472 473 static VAStatus tng__H264ES_process_misc_cir_param(context_ENC_p ctx, object_buffer_p obj_buffer) 474 { 475 VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *)obj_buffer->buffer_data; 476 VAEncMiscParameterCIR *psMiscCirParams = NULL; 477 478 ASSERT(obj_buffer->type == VAEncMiscParameterTypeCIR); 479 ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterCIR)); 480 481 psMiscCirParams = (VAEncMiscParameterCIR*)pBuffer->data; 482 483 if (psMiscCirParams->cir_num_mbs > 0) { 484 drv_debug_msg(VIDEO_DEBUG_GENERAL, 485 "CIR enabled with MB count %d\n", ctx->ui16IntraRefresh); 486 ctx->ui16IntraRefresh = psMiscCirParams->cir_num_mbs; 487 ctx->bEnableCIR = 1; 488 ctx->bEnableInpCtrl = 1; 489 ctx->bEnableHostBias = 1; 490 } else { 491 drv_debug_msg(VIDEO_DEBUG_ERROR, 492 "%s: ERROR: invalid cir num mbs(%d), should bigger than 0\n", 493 __FUNCTION__, ctx->ui16IntraRefresh); 494 return VA_STATUS_ERROR_INVALID_PARAMETER; 495 } 496 497 return VA_STATUS_SUCCESS; 498 } 499 500 static IMG_UINT8 tng__H264ES_calculate_level(context_ENC_p ctx) 501 { 502 IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); 503 IMG_UINT32 ui32MBf=0; 504 IMG_UINT32 ui32MBs; 505 IMG_UINT32 ui32Level=0; 506 IMG_UINT32 ui32TempLevel=0; 507 IMG_UINT32 ui32DpbMbs; 508 // We need to calculate the level based on a few constraints these are 509 // Macroblocks per second 510 // picture size 511 // decoded picture buffer size, and bitrate 512 ui32MBf = (ctx->ui16Width)*(ctx->ui16FrameHeight) >> 8; 513 ui32MBs = ui32MBf * psRCParams->ui32FrameRate; 514 515 516 // could do these in nice tables, but this is clearer 517 if (ui32MBf > 22080) ui32Level = SH_LEVEL_51; 518 else if (ui32MBf > 8704) ui32Level = SH_LEVEL_50; 519 else if (ui32MBf > 8192) ui32Level = SH_LEVEL_42; 520 else if (ui32MBf > 5120) ui32Level = SH_LEVEL_40; 521 else if (ui32MBf > 3600) ui32Level = SH_LEVEL_32; 522 else if (ui32MBf > 1620) ui32Level = SH_LEVEL_31; 523 else if (ui32MBf > 792) ui32Level = SH_LEVEL_22; 524 else if (ui32MBf > 396) ui32Level = SH_LEVEL_21; 525 else if (ui32MBf > 99) ui32Level = SH_LEVEL_11; 526 else ui32Level = SH_LEVEL_10; 527 528 drv_debug_msg(VIDEO_DEBUG_GENERAL, 529 "%s: ui32MBf = %d, ui32MBs = %d, ui32Level = %d\n", 530 __FUNCTION__, ui32MBf, ui32MBs, ui32Level); 531 532 //ui32DpbMbs = ui32MBf * (psContext->ui32MaxNumRefFrames + 1); 533 ui32DpbMbs = ui32MBf * (ctx->ui8MaxNumRefFrames + 1); 534 535 if (ui32DpbMbs > 110400) ui32TempLevel = SH_LEVEL_51; 536 else if (ui32DpbMbs > 34816) ui32TempLevel = SH_LEVEL_50; 537 else if (ui32DpbMbs > 32768) ui32TempLevel = SH_LEVEL_42; 538 else if (ui32DpbMbs > 20480) ui32TempLevel = SH_LEVEL_40; 539 else if (ui32DpbMbs > 18000) ui32TempLevel = SH_LEVEL_32; 540 else if (ui32DpbMbs > 8100) ui32TempLevel = SH_LEVEL_31; 541 else if (ui32DpbMbs > 4752) ui32TempLevel = SH_LEVEL_22; 542 else if (ui32DpbMbs > 2376) ui32TempLevel = SH_LEVEL_21; 543 else if (ui32DpbMbs > 900) ui32TempLevel = SH_LEVEL_12; 544 else if (ui32DpbMbs > 396) ui32TempLevel = SH_LEVEL_11; 545 else ui32TempLevel = SH_LEVEL_10; 546 ui32Level = tng__max(ui32Level, ui32TempLevel); 547 548 drv_debug_msg(VIDEO_DEBUG_GENERAL, 549 "%s: ui32DpbMbs = %d, ui32Level = %d\n", 550 __FUNCTION__, ui32DpbMbs, ui32Level); 551 552 // now restrict based on the number of macroblocks per second 553 if (ui32MBs > 589824) ui32TempLevel = SH_LEVEL_51; 554 else if (ui32MBs > 522240) ui32TempLevel = SH_LEVEL_50; 555 else if (ui32MBs > 245760) ui32TempLevel = SH_LEVEL_42; 556 else if (ui32MBs > 216000) ui32TempLevel = SH_LEVEL_40; 557 else if (ui32MBs > 108000) ui32TempLevel = SH_LEVEL_32; 558 else if (ui32MBs > 40500) ui32TempLevel = SH_LEVEL_31; 559 else if (ui32MBs > 20250) ui32TempLevel = SH_LEVEL_30; 560 else if (ui32MBs > 19800) ui32TempLevel = SH_LEVEL_22; 561 else if (ui32MBs > 11880) ui32TempLevel = SH_LEVEL_21; 562 else if (ui32MBs > 6000) ui32TempLevel = SH_LEVEL_13; 563 else if (ui32MBs > 3000) ui32TempLevel = SH_LEVEL_12; 564 else if (ui32MBs > 1485) ui32TempLevel = SH_LEVEL_11; 565 else ui32TempLevel = SH_LEVEL_10; 566 ui32Level = tng__max(ui32Level, ui32TempLevel); 567 568 drv_debug_msg(VIDEO_DEBUG_GENERAL, 569 "%s: ui32TempLevel = %d, ui32Level = %d\n", 570 __FUNCTION__, ui32TempLevel, ui32Level); 571 572 if (psRCParams->bRCEnable) { 573 // now restrict based on the requested bitrate 574 if (psRCParams->ui32FrameRate > 135000000) ui32TempLevel = SH_LEVEL_51; 575 else if (psRCParams->ui32FrameRate > 50000000) ui32TempLevel = SH_LEVEL_50; 576 else if (psRCParams->ui32FrameRate > 20000000) ui32TempLevel = SH_LEVEL_41; 577 else if (psRCParams->ui32FrameRate > 14000000) ui32TempLevel = SH_LEVEL_32; 578 else if (psRCParams->ui32FrameRate > 10000000) ui32TempLevel = SH_LEVEL_31; 579 else if (psRCParams->ui32FrameRate > 4000000) ui32TempLevel = SH_LEVEL_30; 580 else if (psRCParams->ui32FrameRate > 2000000) ui32TempLevel = SH_LEVEL_21; 581 else if (psRCParams->ui32FrameRate > 768000) ui32TempLevel = SH_LEVEL_20; 582 else if (psRCParams->ui32FrameRate > 384000) ui32TempLevel = SH_LEVEL_13; 583 else if (psRCParams->ui32FrameRate > 192000) ui32TempLevel = SH_LEVEL_12; 584 else if (psRCParams->ui32FrameRate > 128000) ui32TempLevel = SH_LEVEL_11; 585 else if (psRCParams->ui32FrameRate > 64000) ui32TempLevel = SH_LEVEL_1B; 586 else ui32TempLevel = SH_LEVEL_10; 587 588 ui32Level = tng__max(ui32Level, ui32TempLevel); 589 } 590 /* 591 if (pParams->bLossless) { 592 ui32Level = tng__max(ui32Level, 320); 593 } 594 */ 595 drv_debug_msg(VIDEO_DEBUG_GENERAL, 596 "%s: target level is %d, input level is %d\n", 597 __FUNCTION__, ui32Level, ctx->ui8LevelIdc); 598 return (IMG_UINT8)ui32Level; 599 } 600 601 static VAStatus tng__H264ES_process_sequence_param(context_ENC_p ctx, object_buffer_p obj_buffer) 602 { 603 VAStatus vaStatus = VA_STATUS_SUCCESS; 604 VAEncSequenceParameterBufferH264 *psSeqParams; 605 H264_CROP_PARAMS* psCropParams = &(ctx->sCropParams); 606 IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); 607 FRAME_ORDER_INFO *psFrameInfo = &(ctx->sFrameOrderInfo); 608 H264_VUI_PARAMS *psVuiParams = &(ctx->sVuiParams); 609 IMG_UINT32 ui32MaxUnit32 = (IMG_UINT32)0x7ffa; 610 IMG_UINT32 ui32IPCount = 0; 611 IMG_UINT64 ui64Temp = 0; 612 613 ASSERT(obj_buffer->type == VAEncSequenceParameterBufferType); 614 ASSERT(obj_buffer->size == sizeof(VAEncSequenceParameterBufferH264)); 615 616 if (obj_buffer->size != sizeof(VAEncSequenceParameterBufferH264)) { 617 vaStatus = VA_STATUS_ERROR_UNKNOWN; 618 goto out1; 619 } 620 621 ctx->obj_context->frame_count = 0; 622 psSeqParams = (VAEncSequenceParameterBufferH264 *) obj_buffer->buffer_data; 623 obj_buffer->buffer_data = NULL; 624 obj_buffer->size = 0; 625 626 #ifdef _TOPAZHP_PDUMP_ 627 tng_H264ES_trace_seq_params(psSeqParams); 628 #endif 629 630 ctx->ui8LevelIdc = psSeqParams->level_idc; 631 ctx->ui8MaxNumRefFrames = psSeqParams->max_num_ref_frames; 632 633 ctx->ui32IdrPeriod = psSeqParams->intra_idr_period; 634 ctx->ui32IntraCnt = psSeqParams->intra_period; 635 ui32IPCount = (IMG_UINT32)(psSeqParams->ip_period); 636 637 if ((ui32IPCount > 4) || (ui32IPCount == 0)) { 638 drv_debug_msg(VIDEO_DEBUG_ERROR, 639 "%s: ip_period %d, it should be in [1, 4]\n", 640 __FUNCTION__, psSeqParams->ip_period); 641 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 642 goto out1; 643 } 644 645 if (ctx->ui32IntraCnt == 0) { 646 if (ui32IPCount == 1) 647 ctx->ui32IntraCnt = INT_MAX; 648 else 649 ctx->ui32IntraCnt = INT_MAX - (INT_MAX % ui32IPCount); 650 ctx->ui32IdrPeriod = 1; 651 } else if (ctx->ui32IntraCnt == 1) { 652 //only I frame or IDR frames; 653 ui32IPCount = 1; 654 if (ctx->ui32IdrPeriod == 0) 655 ctx->ui32IdrPeriod = INT_MAX; 656 } else { 657 if (ctx->ui32IdrPeriod == 0) { 658 ctx->ui32IdrPeriod = INT_MAX / ctx->ui32IntraCnt; 659 } else if (ctx->ui32IdrPeriod > 1) { 660 ui64Temp = (IMG_UINT64)(ctx->ui32IdrPeriod) * (IMG_UINT64)(ctx->ui32IntraCnt); 661 if (ui64Temp >= (IMG_UINT64)INT_MAX) { 662 ctx->ui32IdrPeriod = INT_MAX / ctx->ui32IntraCnt; 663 } 664 } 665 666 if ((ctx->ui32IntraCnt % ui32IPCount) != 0) { 667 if (ctx->ui32IntraCnt > INT_MAX - ui32IPCount + (ctx->ui32IntraCnt % ui32IPCount)) 668 ctx->ui32IntraCnt = INT_MAX - ui32IPCount + (ctx->ui32IntraCnt % ui32IPCount); 669 else 670 ctx->ui32IntraCnt += ui32IPCount - (ctx->ui32IntraCnt % ui32IPCount); 671 } 672 } 673 674 if (ctx->ui32FrameCount[ctx->ui32StreamID] > 0) { 675 ctx->idr_force_flag = 1; 676 if (ctx->ui32IntraCntSave != ctx->ui32IntraCnt) { 677 drv_debug_msg(VIDEO_DEBUG_GENERAL, 678 "%s: intra_period updated from %d to %d\n", 679 __FUNCTION__, ctx->ui32IntraCntSave, ctx->ui32IntraCnt); 680 ctx->rc_update_flag |= RC_MASK_intra_period; 681 } 682 } 683 684 ctx->ui32IntraCntSave = ctx->ui32IntraCnt; 685 686 ctx->ui8SlotsInUse = ui32IPCount + 1; //Bframes + 2 687 688 //bits per second 689 if (!psSeqParams->bits_per_second) { 690 psSeqParams->bits_per_second = ctx->ui16Width * ctx->ui16PictureHeight * 30 * 12; 691 } 692 693 if (psSeqParams->bits_per_second > TOPAZ_H264_MAX_BITRATE) { 694 psSeqParams->bits_per_second = TOPAZ_H264_MAX_BITRATE; 695 drv_debug_msg(VIDEO_DEBUG_ERROR, 696 "%s: bits_per_second(%d) exceeds the maximum bitrate, set it with %d\n", 697 __FUNCTION__, psSeqParams->bits_per_second, 698 TOPAZ_H264_MAX_BITRATE); 699 } 700 701 if (psRCParams->ui32BitsPerSecond == 0) 702 psRCParams->ui32BitsPerSecond = psSeqParams->bits_per_second; 703 704 if (psSeqParams->bits_per_second != psRCParams->ui32BitsPerSecond) { 705 psRCParams->ui32BitsPerSecond = psSeqParams->bits_per_second; 706 ctx->rc_update_flag |= RC_MASK_bits_per_second; 707 } 708 709 psRCParams->ui32IntraFreq = ctx->ui32IntraCnt; 710 psRCParams->ui32TransferBitsPerSecond = psRCParams->ui32BitsPerSecond; 711 psRCParams->ui16BFrames = ui32IPCount - 1; 712 713 if (psRCParams->ui32FrameRate == 0) 714 psRCParams->ui32FrameRate = 30; 715 716 //set the B frames 717 if (psRCParams->eRCMode == IMG_RCMODE_VCM) 718 psRCParams->ui16BFrames = 0; 719 720 if ((psRCParams->ui16BFrames > 0) && (ctx->ui8ProfileIdc == H264ES_PROFILE_BASELINE)) { 721 ctx->ui8ProfileIdc = H264ES_PROFILE_MAIN; 722 } 723 724 if (psFrameInfo->slot_consume_dpy_order != NULL) 725 free(psFrameInfo->slot_consume_dpy_order); 726 if (psFrameInfo->slot_consume_enc_order != NULL) 727 free(psFrameInfo->slot_consume_enc_order); 728 729 if (psRCParams->ui16BFrames != 0) { 730 memset(psFrameInfo, 0, sizeof(FRAME_ORDER_INFO)); 731 psFrameInfo->slot_consume_dpy_order = (int *)malloc(ctx->ui8SlotsInUse * sizeof(int)); 732 psFrameInfo->slot_consume_enc_order = (int *)malloc(ctx->ui8SlotsInUse * sizeof(int)); 733 734 if ((psFrameInfo->slot_consume_dpy_order == NULL) || 735 (psFrameInfo->slot_consume_enc_order == NULL)) { 736 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: error malloc slot order array\n", __FUNCTION__); 737 } 738 } 739 740 //set the crop parameters 741 psCropParams->bClip = psSeqParams->frame_cropping_flag; 742 psCropParams->ui16LeftCropOffset = psSeqParams->frame_crop_left_offset; 743 psCropParams->ui16RightCropOffset = psSeqParams->frame_crop_right_offset; 744 psCropParams->ui16TopCropOffset = psSeqParams->frame_crop_top_offset; 745 psCropParams->ui16BottomCropOffset = psSeqParams->frame_crop_bottom_offset; 746 747 //set level idc parameter 748 ctx->ui32VertMVLimit = 255 ;//(63.75 in qpel increments) 749 ctx->bLimitNumVectors = IMG_FALSE; 750 751 if (ctx->ui8LevelIdc == 111) 752 ctx->ui8LevelIdc = SH_LEVEL_1B; 753 754 ctx->ui8LevelIdc = tng__H264ES_calculate_level(ctx); 755 756 /*Setting VertMVLimit and LimitNumVectors only for H264*/ 757 if (ctx->ui8LevelIdc >= SH_LEVEL_30) 758 ctx->bLimitNumVectors = IMG_TRUE; 759 else 760 ctx->bLimitNumVectors = IMG_FALSE; 761 762 if (ctx->ui8LevelIdc >= SH_LEVEL_31) 763 ctx->ui32VertMVLimit = 2047 ;//(511.75 in qpel increments) 764 else if (ctx->ui8LevelIdc >= SH_LEVEL_21) 765 ctx->ui32VertMVLimit = 1023 ;//(255.75 in qpel increments) 766 else if (ctx->ui8LevelIdc >= SH_LEVEL_11) 767 ctx->ui32VertMVLimit = 511 ;//(127.75 in qpel increments) 768 769 //set VUI info 770 memset(psVuiParams, 0, sizeof(H264_VUI_PARAMS)); 771 if (psSeqParams->time_scale != 0 && psSeqParams->num_units_in_tick != 0 772 && (psSeqParams->time_scale > psSeqParams->num_units_in_tick)) { 773 psVuiParams->Time_Scale = psSeqParams->time_scale; 774 psVuiParams->num_units_in_tick = psSeqParams->num_units_in_tick; 775 } 776 777 out1: 778 free(obj_buffer->buffer_data); 779 obj_buffer->buffer_data = NULL; 780 obj_buffer->size = 0; 781 782 return vaStatus; 783 } 784 785 #if 0 786 static VAStatus tng__H264ES_process_picture_param(context_ENC_p ctx, object_buffer_p obj_buffer) 787 { 788 VAStatus vaStatus = VA_STATUS_SUCCESS; 789 context_ENC_mem *ps_mem = &(ctx->ctx_mem[ctx->ui32StreamID]); 790 context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf[ctx->ui32StreamID]); 791 IMG_RC_PARAMS * psRCParams = &(ctx->sRCParams); 792 VAEncPictureParameterBufferH264 *psPicParams; 793 IMG_BOOL bDepViewPPS = IMG_FALSE; 794 795 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: start\n",__FUNCTION__); 796 ASSERT(obj_buffer->type == VAEncPictureParameterBufferType); 797 if (obj_buffer->size != sizeof(VAEncPictureParameterBufferH264)) { 798 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalid coded buffer handle\n", __FUNCTION__, __LINE__); 799 return VA_STATUS_ERROR_UNKNOWN; 800 } 801 802 /* Transfer ownership of VAEncPictureParameterBufferH264 data */ 803 psPicParams = (VAEncPictureParameterBufferH264 *) obj_buffer->buffer_data; 804 805 obj_buffer->buffer_data = NULL; 806 obj_buffer->size = 0; 807 808 ASSERT(ctx->ui16Width == psPicParams->picture_width); 809 ASSERT(ctx->ui16PictureHeight == psPicParams->picture_height); 810 811 #ifdef _TOPAZHP_OLD_LIBVA_ 812 ps_buf->ref_surface = SURFACE(psPicParams->ReferenceFrames[0].picture_id); 813 ps_buf->coded_buf = BUFFER(psPicParams->coded_buf); 814 #else 815 { 816 IMG_INT32 i; 817 ps_buf->rec_surface = SURFACE(psPicParams->CurrPic.picture_id); 818 for (i = 0; i < 16; i++) 819 ps_buf->ref_surface[i] = SURFACE(psPicParams->ReferenceFrames[i].picture_id); 820 ps_buf->coded_buf = BUFFER(psPicParams->coded_buf); 821 } 822 #endif 823 824 if (NULL == ps_buf->coded_buf) { 825 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalid coded buffer handle\n", __FUNCTION__, __LINE__); 826 free(psPicParams); 827 return VA_STATUS_ERROR_INVALID_BUFFER; 828 } 829 830 if ((ctx->bEnableMvc) && (ctx->ui16MVCViewIdx != 0) && 831 (ctx->ui16MVCViewIdx != (IMG_UINT16)(NON_MVC_VIEW))) { 832 bDepViewPPS = IMG_TRUE; 833 } 834 835 /************* init **************** 836 ctx->bCabacEnabled = psPicParams->pic_fields.bits.entropy_coding_mode_flag; 837 ctx->bH2648x8Transform = psPicParams->pic_fields.bits.transform_8x8_mode_flag; 838 ctx->bH264IntraConstrained = psPicParams->pic_fields.bits.constrained_intra_pred_flag; 839 ctx->bWeightedPrediction = psPicParams->pic_fields.bits.weighted_pred_flag; 840 ctx->ui8VPWeightedImplicitBiPred = psPicParams->pic_fields.bits.weighted_bipred_idc; 841 ctx->bCustomScaling = psPicParams->pic_fields.bits.pic_scaling_matrix_present_flag; 842 ************* set rc params *************/ 843 // ctx->sRCParams.ui32InitialQp = psPicParams->pic_init_qp; 844 // ctx->sRCParams.i8QCPOffset = psPicParams->chroma_qp_index_offset; 845 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s psRCParams->ui32InitialQp = %d, psRCParams->iMinQP = %d\n", __FUNCTION__, psPicParams->pic_init_qp, psPicParams->chroma_qp_index_offset); 846 tng__H264ES_prepare_picture_header( 847 ps_mem->bufs_pic_template.virtual_addr, 848 0, //IMG_BOOL bCabacEnabled, 849 ctx->bH2648x8Transform, //IMG_BOOL b_8x8transform, 850 0, //IMG_BOOL bIntraConstrained, 851 0, //IMG_INT8 i8CQPOffset, 852 0, //IMG_BOOL bWeightedPrediction, 853 0, //IMG_UINT8 ui8WeightedBiPred, 854 0, //IMG_BOOL bMvcPPS, 855 0, //IMG_BOOL bScalingMatrix, 856 0 //IMG_BOOL bScalingLists 857 ); 858 free(psPicParams); 859 /* 860 if (psRCParams->ui16BFrames == 0) { 861 tng_send_codedbuf(ctx, (ctx->obj_context->frame_count&1)); 862 tng_send_source_frame(ctx, (ctx->obj_context->frame_count&1), ctx->obj_context->frame_count); 863 } else 864 tng__H264ES_provide_buffer_for_BFrames(ctx); 865 */ 866 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: end\n",__FUNCTION__); 867 868 return vaStatus; 869 } 870 #endif 871 872 static VAStatus tng__H264ES_process_picture_param_base(context_ENC_p ctx, unsigned char *buf) 873 { 874 VAStatus vaStatus = VA_STATUS_SUCCESS; 875 context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf); 876 VAEncPictureParameterBufferH264 *psPicParams; 877 #ifndef _TNG_FRAMES_ 878 IMG_INT32 i; 879 #endif 880 psPicParams = (VAEncPictureParameterBufferH264 *) buf; 881 882 #ifdef _TOPAZHP_PDUMP_ 883 tng_H264ES_trace_pic_params(psPicParams); 884 #endif 885 886 #ifdef _TNG_FRAMES_ 887 ps_buf->rec_surface = SURFACE(psPicParams->CurrPic.picture_id); 888 ps_buf->ref_surface = SURFACE(psPicParams->ReferenceFrames[0].picture_id); 889 ps_buf->ref_surface1 = SURFACE(psPicParams->ReferenceFrames[1].picture_id); 890 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: psPicParams->coded_buf = 0x%08x, ps_buf->coded_buf = 0x%08x\n", 891 __FUNCTION__, psPicParams->coded_buf, ps_buf->coded_buf); 892 #else 893 { 894 ps_buf->rec_surface = SURFACE(psPicParams->CurrPic.picture_id); 895 for (i = 0; i < 4; i++) { 896 ps_buf->ref_surface[i] = SURFACE(psPicParams->ReferenceFrames[i].picture_id); 897 ps_buf->ref_surface[i]->is_ref_surface = 1; 898 } 899 } 900 #endif 901 902 ps_buf->coded_buf = BUFFER(psPicParams->coded_buf); 903 904 if (NULL == ps_buf->coded_buf) { 905 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalid coded buffer handle\n", __FUNCTION__, __LINE__); 906 free(psPicParams); 907 return VA_STATUS_ERROR_INVALID_BUFFER; 908 } 909 910 ctx->bH2648x8Transform = psPicParams->pic_fields.bits.transform_8x8_mode_flag; 911 if ((ctx->bH2648x8Transform == 1) && (ctx->ui8ProfileIdc != H264ES_PROFILE_HIGH)) { 912 drv_debug_msg(VIDEO_DEBUG_ERROR, 913 "%s L%d only high profile could set bH2648x8Transform TRUE\n", 914 __FUNCTION__, __LINE__); 915 ctx->bH2648x8Transform = 0; 916 } 917 918 ctx->bH264IntraConstrained = psPicParams->pic_fields.bits.constrained_intra_pred_flag; 919 if (ctx->bEnableMVC == 1) { 920 drv_debug_msg(VIDEO_DEBUG_ERROR, 921 "%s L%d MVC could not set bH264IntraConstrained TRUE\n", 922 __FUNCTION__, __LINE__); 923 ctx->bH264IntraConstrained = 0; 924 } 925 926 ctx->bCabacEnabled = psPicParams->pic_fields.bits.entropy_coding_mode_flag; 927 ctx->bWeightedPrediction = psPicParams->pic_fields.bits.weighted_pred_flag; 928 ctx->ui8VPWeightedImplicitBiPred = psPicParams->pic_fields.bits.weighted_bipred_idc; 929 930 /************* init **************** 931 ctx->bCustomScaling = psPicParams->pic_fields.bits.pic_scaling_matrix_present_flag; 932 ************* set rc params *************/ 933 if (ctx->sRCParams.ui32InitialQp == 0) 934 ctx->sRCParams.ui32InitialQp = psPicParams->pic_init_qp; 935 936 ctx->ui32LastPicture = psPicParams->last_picture; 937 938 return vaStatus; 939 } 940 941 static VAStatus tng__H264ES_process_picture_param_mvc(context_ENC_p ctx, unsigned char *buf) 942 { 943 VAStatus vaStatus = VA_STATUS_SUCCESS; 944 VAEncPictureParameterBufferH264_MVC *psPicMvcParams; 945 946 psPicMvcParams = (VAEncPictureParameterBufferH264_MVC *) buf; 947 ctx->ui16MVCViewIdx = ctx->ui32StreamID = psPicMvcParams->view_id; 948 //vaStatus = tng__H264ES_process_picture_param_base(ctx, (unsigned char*)&(psPicMvcParams->base_picture_param)); 949 950 return vaStatus; 951 } 952 953 static VAStatus tng__H264ES_process_picture_param(context_ENC_p ctx, object_buffer_p obj_buffer) 954 { 955 VAStatus vaStatus = VA_STATUS_SUCCESS; 956 957 ASSERT(obj_buffer->type == VAEncPictureParameterBufferType); 958 959 drv_debug_msg(VIDEO_DEBUG_GENERAL, 960 "%s: ctx->bEnableMVC = %d\n", __FUNCTION__, ctx->bEnableMVC); 961 962 if (ctx->bEnableMVC) { 963 if (obj_buffer->size != sizeof(VAEncPictureParameterBufferH264_MVC)) { 964 drv_debug_msg(VIDEO_DEBUG_ERROR, 965 "%s L%d Invalid picture parameter H264 mvc buffer handle\n", 966 __FUNCTION__, __LINE__); 967 return VA_STATUS_ERROR_UNKNOWN; 968 } 969 vaStatus = tng__H264ES_process_picture_param_mvc(ctx, obj_buffer->buffer_data); 970 } else { 971 if (obj_buffer->size != sizeof(VAEncPictureParameterBufferH264)) { 972 drv_debug_msg(VIDEO_DEBUG_ERROR, 973 "%s L%d Invalid picture parameter H264 buffer handle\n", 974 __FUNCTION__, __LINE__); 975 return VA_STATUS_ERROR_UNKNOWN; 976 } 977 vaStatus = tng__H264ES_process_picture_param_base(ctx, obj_buffer->buffer_data); 978 } 979 free(obj_buffer->buffer_data); 980 obj_buffer->buffer_data = NULL; 981 obj_buffer->size = 0; 982 return vaStatus; 983 } 984 985 static VAStatus tng__H264ES_process_slice_param_mrfld(context_ENC_p ctx, object_buffer_p obj_buffer) 986 { 987 VAStatus vaStatus = VA_STATUS_SUCCESS; 988 VAEncSliceParameterBufferH264 *psSliceParamsH264; 989 unsigned int i; 990 unsigned int uiPreMBAddress = 0; 991 unsigned int uiCurMBAddress = 0; 992 unsigned int uiPreMBNumbers = 0; 993 unsigned int uiCurMBNumbers = 0; 994 unsigned int uiAllMBNumbers = 0; 995 unsigned char ucPreDeblockIdc = 0; 996 unsigned char ucCurDeblockIdc = 0; 997 998 /* Transfer ownership of VAEncPictureParameterBufferH264 data */ 999 psSliceParamsH264 = (VAEncSliceParameterBufferH264*) obj_buffer->buffer_data; 1000 1001 #ifdef _TOPAZHP_PDUMP_ 1002 tng_H264ES_trace_slice_params(psSliceParamsH264); 1003 #endif 1004 1005 ucPreDeblockIdc = psSliceParamsH264->disable_deblocking_filter_idc; 1006 1007 for (i = 0; i < obj_buffer->num_elements; i++) { 1008 uiCurMBAddress = psSliceParamsH264->macroblock_address; 1009 uiCurMBNumbers = psSliceParamsH264->num_macroblocks; 1010 if (uiCurMBAddress != uiPreMBAddress + uiPreMBNumbers) { 1011 drv_debug_msg(VIDEO_DEBUG_ERROR, 1012 "%s L%d Error Macroblock Address (%d), address (%d), number (%d)\n", 1013 __FUNCTION__, __LINE__, i, psSliceParamsH264->macroblock_address, 1014 psSliceParamsH264->num_macroblocks); 1015 return VA_STATUS_ERROR_INVALID_PARAMETER; 1016 } 1017 uiPreMBNumbers = uiCurMBNumbers; 1018 uiPreMBAddress = uiCurMBAddress; 1019 uiAllMBNumbers += uiCurMBNumbers; 1020 1021 ucCurDeblockIdc = psSliceParamsH264->disable_deblocking_filter_idc; 1022 if (ucPreDeblockIdc != ucCurDeblockIdc) { 1023 drv_debug_msg(VIDEO_DEBUG_ERROR, 1024 "%s L%d Error Macroblock Address (%d), deblock idc pre (%d), cur (%d)\n", 1025 __FUNCTION__, __LINE__, i, ucPreDeblockIdc, ucCurDeblockIdc); 1026 return VA_STATUS_ERROR_INVALID_PARAMETER; 1027 } 1028 psSliceParamsH264++; 1029 } 1030 1031 if (uiAllMBNumbers != (unsigned int)(((IMG_UINT16)(ctx->ui16Width) * (IMG_UINT16)(ctx->ui16PictureHeight)) >> 8)) { 1032 drv_debug_msg(VIDEO_DEBUG_ERROR, 1033 "%s L%d Error Macroblock all number (%d), (%d)\n", 1034 __FUNCTION__, __LINE__, i, uiAllMBNumbers, 1035 ((ctx->ui16Width * ctx->ui16PictureHeight) >> 8)); 1036 return VA_STATUS_ERROR_INVALID_PARAMETER; 1037 } 1038 1039 //deblocking behaviour 1040 ctx->bArbitrarySO = IMG_FALSE; 1041 ctx->ui8DeblockIDC = ucCurDeblockIdc; 1042 ctx->ui8SlicesPerPicture = obj_buffer->num_elements; 1043 1044 return vaStatus; 1045 } 1046 1047 static VAStatus tng__H264ES_process_slice_param_mdfld(context_ENC_p ctx, object_buffer_p obj_buffer) 1048 { 1049 VAStatus vaStatus = VA_STATUS_SUCCESS; 1050 VAEncSliceParameterBuffer *psSliceParams = NULL; 1051 psSliceParams = (VAEncSliceParameterBuffer*) obj_buffer->buffer_data; 1052 1053 //deblocking behaviour 1054 ctx->bArbitrarySO = IMG_FALSE; 1055 ctx->ui8DeblockIDC = psSliceParams->slice_flags.bits.disable_deblocking_filter_idc; 1056 ctx->ui8SlicesPerPicture = obj_buffer->num_elements; 1057 return vaStatus; 1058 } 1059 1060 static VAStatus tng__H264ES_process_misc_max_slice_size_param(context_ENC_p ctx, object_buffer_p obj_buffer) 1061 { 1062 VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data; 1063 VAEncMiscParameterMaxSliceSize *psMiscMaxSliceSizeParams = NULL; 1064 IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); 1065 1066 ASSERT(obj_buffer->type == VAEncMiscParameterTypeMaxSliceSize); 1067 ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterMaxSliceSize)); 1068 1069 psMiscMaxSliceSizeParams = (VAEncMiscParameterMaxSliceSize*)pBuffer->data; 1070 1071 if (psMiscMaxSliceSizeParams->max_slice_size > 0) { 1072 psRCParams->ui32SliceByteLimit = psMiscMaxSliceSizeParams->max_slice_size; 1073 drv_debug_msg(VIDEO_DEBUG_GENERAL, 1074 "Max slice size is %d\n", psRCParams->ui32SliceByteLimit); 1075 } else { 1076 drv_debug_msg(VIDEO_DEBUG_ERROR, 1077 "%s: ERROR: invalid max slice size(%d), should bigger than 0\n", 1078 __FUNCTION__, psMiscMaxSliceSizeParams->max_slice_size); 1079 psRCParams->ui32SliceByteLimit = 0; 1080 return VA_STATUS_ERROR_INVALID_PARAMETER; 1081 } 1082 1083 return VA_STATUS_SUCCESS; 1084 } 1085 1086 static VAStatus tng__H264ES_process_slice_param(context_ENC_p ctx, object_buffer_p obj_buffer) 1087 { 1088 VAStatus vaStatus = VA_STATUS_SUCCESS; 1089 ASSERT(obj_buffer->type == VAEncSliceParameterBufferType); 1090 /* Prepare InParams for macros of current slice, insert slice header, insert do slice command */ 1091 1092 if (obj_buffer->size == sizeof(VAEncSliceParameterBufferH264)) { 1093 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Receive VAEncSliceParameterBufferH264 buffer\n"); 1094 vaStatus = tng__H264ES_process_slice_param_mrfld(ctx, obj_buffer); 1095 } else if (obj_buffer->size == sizeof(VAEncSliceParameterBuffer)) { 1096 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Receive VAEncSliceParameterBuffer buffer\n"); 1097 vaStatus = tng__H264ES_process_slice_param_mdfld(ctx, obj_buffer); 1098 } else { 1099 drv_debug_msg(VIDEO_DEBUG_ERROR, "Buffer size(%d) is wrong. It should be %d or %d\n", 1100 obj_buffer->size, sizeof(VAEncSliceParameterBuffer), 1101 sizeof(VAEncSliceParameterBufferH264)); 1102 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 1103 } 1104 1105 free(obj_buffer->buffer_data); 1106 obj_buffer->size = 0; 1107 obj_buffer->buffer_data = NULL; 1108 return vaStatus; 1109 } 1110 1111 static VAStatus tng__H264ES_process_misc_param(context_ENC_p ctx, object_buffer_p obj_buffer) 1112 { 1113 VAStatus vaStatus = VA_STATUS_SUCCESS; 1114 VAEncMiscParameterBuffer *pBuffer; 1115 1116 ASSERT(obj_buffer->type == VAEncMiscParameterBufferType); 1117 ASSERT(ctx != NULL); 1118 /* Transfer ownership of VAEncMiscParameterBuffer data */ 1119 pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data; 1120 obj_buffer->size = 0; 1121 1122 switch (pBuffer->type) { 1123 case VAEncMiscParameterTypeFrameRate: 1124 vaStatus = tng__H264ES_process_misc_framerate_param(ctx, obj_buffer); 1125 break; 1126 case VAEncMiscParameterTypeRateControl: 1127 vaStatus = tng__H264ES_process_misc_ratecontrol_param(ctx, obj_buffer); 1128 break; 1129 case VAEncMiscParameterTypeHRD: 1130 vaStatus = tng__H264ES_process_misc_hrd_param(ctx, obj_buffer); 1131 break; 1132 case VAEncMiscParameterTypeAIR: 1133 vaStatus = tng__H264ES_process_misc_air_param(ctx, obj_buffer); 1134 break; 1135 case VAEncMiscParameterTypeCIR: 1136 vaStatus = tng__H264ES_process_misc_cir_param(ctx, obj_buffer); 1137 break; 1138 case VAEncMiscParameterTypeMaxSliceSize: 1139 vaStatus = tng__H264ES_process_misc_max_slice_size_param(ctx, obj_buffer); 1140 break; 1141 default: 1142 break; 1143 } 1144 free(obj_buffer->buffer_data); 1145 obj_buffer->buffer_data = NULL; 1146 1147 return vaStatus; 1148 } 1149 1150 static void tng_H264ES_QueryConfigAttributes( 1151 VAProfile __maybe_unused profile, 1152 VAEntrypoint __maybe_unused entrypoint, 1153 VAConfigAttrib *attrib_list, 1154 int num_attribs) 1155 { 1156 int i; 1157 1158 /* RateControl attributes */ 1159 for (i = 0; i < num_attribs; i++) { 1160 switch (attrib_list[i].type) { 1161 case VAConfigAttribRTFormat: 1162 break; 1163 1164 case VAConfigAttribRateControl: 1165 attrib_list[i].value = VA_RC_NONE | VA_RC_CBR | VA_RC_VBR | VA_RC_VCM; 1166 break; 1167 1168 case VAConfigAttribEncAutoReference: 1169 attrib_list[i].value = 1; 1170 break; 1171 1172 case VAConfigAttribEncMaxRefFrames: 1173 attrib_list[i].value = 4; 1174 break; 1175 1176 default: 1177 attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED; 1178 break; 1179 } 1180 } 1181 } 1182 1183 static VAStatus tng_H264ES_ValidateConfig( 1184 object_config_p obj_config) 1185 { 1186 int i; 1187 1188 /* Check all attributes */ 1189 for (i = 0; i < obj_config->attrib_count; i++) { 1190 switch (obj_config->attrib_list[i].type) { 1191 case VAConfigAttribRTFormat: 1192 /* Ignore */ 1193 break; 1194 case VAConfigAttribRateControl: 1195 break; 1196 case VAConfigAttribEncAutoReference: 1197 break; 1198 case VAConfigAttribEncMaxRefFrames: 1199 break; 1200 default: 1201 return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; 1202 } 1203 } 1204 1205 return VA_STATUS_SUCCESS; 1206 } 1207 1208 static VAStatus tng_H264ES_setup_profile_features(context_ENC_p ctx) 1209 { 1210 VAStatus vaStatus = VA_STATUS_SUCCESS; 1211 1212 IMG_ENCODE_FEATURES * pEncFeatures = &ctx->sEncFeatures; 1213 pEncFeatures->bEnable8x16MVDetect = IMG_TRUE; 1214 pEncFeatures->bEnable16x8MVDetect = IMG_TRUE; 1215 1216 return vaStatus; 1217 } 1218 1219 1220 static VAStatus tng_H264ES_CreateContext( 1221 object_context_p obj_context, 1222 object_config_p obj_config) 1223 { 1224 VAStatus vaStatus = VA_STATUS_SUCCESS; 1225 context_ENC_p ctx; 1226 1227 vaStatus = tng_CreateContext(obj_context, obj_config, 0); 1228 1229 if (VA_STATUS_SUCCESS != vaStatus) 1230 return VA_STATUS_ERROR_ALLOCATION_FAILED; 1231 1232 ctx = (context_ENC_p) obj_context->format_data; 1233 ctx->eStandard = IMG_STANDARD_H264; 1234 1235 tng__H264ES_init_context(obj_context, obj_config); 1236 1237 vaStatus = tng__H264ES_init_profile(obj_context, obj_config); 1238 if (vaStatus != VA_STATUS_SUCCESS) { 1239 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__H264ES_init_profile\n", __FUNCTION__); 1240 } 1241 1242 vaStatus = tng__H264ES_init_format_mode(obj_context, obj_config); 1243 if (vaStatus != VA_STATUS_SUCCESS) { 1244 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__H264ES_init_format_mode\n", __FUNCTION__); 1245 } 1246 1247 vaStatus = tng__H264ES_get_codec_type(obj_context, obj_config); 1248 if (vaStatus != VA_STATUS_SUCCESS) { 1249 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__H264ES_init_rc_mode\n", __FUNCTION__); 1250 } 1251 1252 vaStatus = tng_H264ES_setup_profile_features(ctx); 1253 if (vaStatus != VA_STATUS_SUCCESS) { 1254 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__profile_features\n", __FUNCTION__); 1255 } 1256 1257 vaStatus = tng__patch_hw_profile(ctx); 1258 if (vaStatus != VA_STATUS_SUCCESS) { 1259 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__patch_hw_profile\n", __FUNCTION__); 1260 } 1261 1262 return vaStatus; 1263 } 1264 1265 static void tng_H264ES_DestroyContext( 1266 object_context_p obj_context) 1267 { 1268 tng_DestroyContext(obj_context, 0); 1269 } 1270 1271 static VAStatus tng_H264ES_BeginPicture( 1272 object_context_p obj_context) 1273 { 1274 INIT_CONTEXT_H264ES; 1275 VAStatus vaStatus = VA_STATUS_SUCCESS; 1276 vaStatus = tng_BeginPicture(ctx); 1277 return vaStatus; 1278 } 1279 1280 static VAStatus tng_H264ES_RenderPicture( 1281 object_context_p obj_context, 1282 object_buffer_p *buffers, 1283 int num_buffers) 1284 { 1285 INIT_CONTEXT_H264ES; 1286 VAStatus vaStatus = VA_STATUS_SUCCESS; 1287 int i; 1288 1289 for (i = 0; i < num_buffers; i++) { 1290 object_buffer_p obj_buffer = buffers[i]; 1291 drv_debug_msg(VIDEO_DEBUG_GENERAL, 1292 "%s: type = %d, num = %d\n", 1293 __FUNCTION__, obj_buffer->type, num_buffers); 1294 1295 switch (obj_buffer->type) { 1296 case VAEncSequenceParameterBufferType: 1297 drv_debug_msg(VIDEO_DEBUG_GENERAL, 1298 "tng_H264_RenderPicture got VAEncSequenceParameterBufferType\n"); 1299 vaStatus = tng__H264ES_process_sequence_param(ctx, obj_buffer); 1300 DEBUG_FAILURE; 1301 break; 1302 case VAEncPictureParameterBufferType: 1303 drv_debug_msg(VIDEO_DEBUG_GENERAL, 1304 "tng_H264_RenderPicture got VAEncPictureParameterBuffer\n"); 1305 vaStatus = tng__H264ES_process_picture_param(ctx, obj_buffer); 1306 DEBUG_FAILURE; 1307 break; 1308 1309 case VAEncSliceParameterBufferType: 1310 drv_debug_msg(VIDEO_DEBUG_GENERAL, 1311 "tng_H264_RenderPicture got VAEncSliceParameterBufferType\n"); 1312 vaStatus = tng__H264ES_process_slice_param(ctx, obj_buffer); 1313 DEBUG_FAILURE; 1314 break; 1315 1316 case VAEncMiscParameterBufferType: 1317 drv_debug_msg(VIDEO_DEBUG_GENERAL, 1318 "tng_H264_RenderPicture got VAEncMiscParameterBufferType\n"); 1319 vaStatus = tng__H264ES_process_misc_param(ctx, obj_buffer); 1320 DEBUG_FAILURE; 1321 break; 1322 default: 1323 vaStatus = VA_STATUS_ERROR_UNKNOWN; 1324 DEBUG_FAILURE; 1325 } 1326 if (vaStatus != VA_STATUS_SUCCESS) { 1327 break; 1328 } 1329 } 1330 return vaStatus; 1331 } 1332 1333 static VAStatus tng_H264ES_EndPicture( 1334 object_context_p obj_context) 1335 { 1336 INIT_CONTEXT_H264ES; 1337 VAStatus vaStatus = VA_STATUS_SUCCESS; 1338 vaStatus = tng_EndPicture(ctx); 1339 return vaStatus; 1340 } 1341 1342 struct format_vtable_s tng_H264ES_vtable = { 1343 queryConfigAttributes: 1344 tng_H264ES_QueryConfigAttributes, 1345 validateConfig: 1346 tng_H264ES_ValidateConfig, 1347 createContext: 1348 tng_H264ES_CreateContext, 1349 destroyContext: 1350 tng_H264ES_DestroyContext, 1351 beginPicture: 1352 tng_H264ES_BeginPicture, 1353 renderPicture: 1354 tng_H264ES_RenderPicture, 1355 endPicture: 1356 tng_H264ES_EndPicture 1357 }; 1358 1359 /*EOF*/ 1360