1 /* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial portions 14 * of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Zhangfei Zhang <zhangfei.zhang (at) intel.com> 26 * Mingruo Sun <mingruo.sun (at) intel.com> 27 * 28 */ 29 #include "vsp_VPP.h" 30 #include "vsp_vp8.h" 31 #include "psb_buffer.h" 32 #include "psb_surface.h" 33 #include "vsp_cmdbuf.h" 34 #include "psb_drv_debug.h" 35 #include "va/va_enc_vp8.h" 36 37 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; 38 #define INIT_CONTEXT_VPP context_VPP_p ctx = (context_VPP_p) obj_context->format_data; 39 #define CONFIG(id) ((object_config_p) object_heap_lookup( &driver_data->config_heap, id )) 40 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id )) 41 #define BUFFER(id) ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id )) 42 43 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id )) 44 45 #define KB 1024 46 #define MB (KB * KB) 47 #define VSP_VP8ENC_STATE_SIZE (1*MB) 48 49 #define ALIGN_TO_128(value) ((value + 128 - 1) & ~(128 - 1)) 50 51 #define REF_FRAME_WIDTH 1920 52 #define REF_FRAME_HEIGHT 1088 53 #define REF_FRAME_BORDER 32 54 55 #define VP8_ENC_CBR 0 56 #define VP8_ENC_CBR_HRD 1 57 58 #define XMEM_FRAME_BUFFER_SIZE_IN_BYTE ((REF_FRAME_WIDTH + 2 * REF_FRAME_BORDER) * (REF_FRAME_HEIGHT + 2 * REF_FRAME_BORDER) + \ 59 2 * ((REF_FRAME_WIDTH + 2 * REF_FRAME_BORDER) >> 1) * (REF_FRAME_HEIGHT / 2 + REF_FRAME_BORDER)) // Allocated for HD 60 61 enum filter_status { 62 FILTER_DISABLED = 0, 63 FILTER_ENABLED 64 }; 65 66 typedef struct _Ref_frame_surface { 67 struct VssProcPictureVP8 ref_frame_buffers[4]; 68 } ref_frame_surface; 69 70 #define FUNCTION_NAME \ 71 printf("ENTER %s.\n",__FUNCTION__); 72 73 #define EXIT_FUNCTION_NAME \ 74 printf("EXIT %s.\n",__FUNCTION__); 75 76 77 typedef union { 78 struct { 79 /* force this frame to be a keyframe */ 80 unsigned int force_kf : 1; 81 /* don't reference the last frame */ 82 unsigned int no_ref_last : 1; 83 /* don't reference the golden frame */ 84 unsigned int no_ref_gf : 1; 85 /* don't reference the alternate reference frame */ 86 unsigned int no_ref_arf : 1; 87 88 unsigned int upd_last : 1; 89 unsigned int upd_gf : 2; 90 unsigned int upd_arf : 2; 91 unsigned int no_upd_last : 1; 92 unsigned int no_upd_gf : 1; 93 unsigned int no_upd_arf : 1; 94 unsigned int upd_entropy : 1; 95 } bits; 96 unsigned int value; 97 } vp8_fw_pic_flags; 98 99 100 static void vsp_VP8_DestroyContext(object_context_p obj_context); 101 102 static VAStatus vsp__VP8_check_legal_picture(object_context_p obj_context, object_config_p obj_config); 103 104 static void vsp_VP8_QueryConfigAttributes( 105 VAProfile __maybe_unused profile, 106 VAEntrypoint __maybe_unused entrypoint, 107 VAConfigAttrib *attrib_list, 108 int num_attribs) 109 { 110 int i; 111 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s\n", __FUNCTION__); 112 113 for (i = 0; i < num_attribs; i++) { 114 switch (attrib_list[i].type) { 115 case VAConfigAttribRTFormat: 116 break; 117 case VAConfigAttribRateControl: 118 attrib_list[i].value = VA_RC_CBR | VA_RC_VCM | VA_RC_VBR; 119 break; 120 case VAConfigAttribEncAutoReference: 121 attrib_list[i].value = 1; 122 break; 123 case VAConfigAttribEncMaxRefFrames: 124 attrib_list[i].value = 4; 125 break; 126 case VAConfigAttribEncRateControlExt: 127 attrib_list[i].value = 3; 128 break; 129 130 default: 131 attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED; 132 break; 133 } 134 } 135 } 136 137 static VAStatus vsp_VP8_ValidateConfig( 138 object_config_p obj_config) 139 { 140 int i; 141 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s\n", __FUNCTION__); 142 143 /* Check all attributes */ 144 for (i = 0; i < obj_config->attrib_count; i++) { 145 switch (obj_config->attrib_list[i].type) { 146 case VAConfigAttribRTFormat: 147 /* Ignore */ 148 break; 149 case VAConfigAttribRateControl: 150 break; 151 case VAConfigAttribEncAutoReference: 152 break; 153 case VAConfigAttribEncMaxRefFrames: 154 break; 155 case VAConfigAttribEncRateControlExt: 156 break; 157 158 default: 159 return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; 160 } 161 } 162 163 return VA_STATUS_SUCCESS; 164 } 165 166 void vsp_VP8_set_default_params(struct VssVp8encSequenceParameterBuffer *vp8_seq) 167 { 168 169 vp8_seq->frame_width = 1280; 170 vp8_seq->frame_height = 720; 171 vp8_seq->frame_rate = 30; 172 vp8_seq->error_resilient = 0; 173 vp8_seq->num_token_partitions = 2; 174 vp8_seq->kf_mode = 1; 175 vp8_seq->kf_min_dist = 0; 176 vp8_seq->kf_max_dist = 30; 177 vp8_seq->rc_target_bitrate = 2000; 178 vp8_seq->rc_min_quantizer = 4; 179 vp8_seq->rc_max_quantizer = 63; 180 vp8_seq->rc_undershoot_pct = 100; 181 vp8_seq->rc_overshoot_pct = 100; 182 vp8_seq->rc_end_usage = VP8_ENC_CBR; 183 vp8_seq->rc_buf_sz = 6000; 184 vp8_seq->rc_buf_initial_sz = 4000; 185 vp8_seq->rc_buf_optimal_sz = 5000; 186 vp8_seq->max_intra_rate = 0; 187 vp8_seq->cyclic_intra_refresh = 0; 188 vp8_seq->concatenate_partitions = 1; 189 vp8_seq->recon_buffer_mode = vss_vp8enc_seq_param_recon_buffer_mode_per_seq; 190 vp8_seq->ts_number_layers = 1; 191 vp8_seq->ts_layer_id[0] = 0; 192 vp8_seq->ts_rate_decimator[0] = 0; 193 vp8_seq->ts_periodicity = 0; 194 vp8_seq->ts_target_bitrate[0] = 0; 195 } 196 197 static VAStatus vsp_VP8_CreateContext( 198 object_context_p obj_context, 199 object_config_p obj_config) 200 { 201 VAStatus vaStatus = VA_STATUS_SUCCESS; 202 /* currently vp8 will use vpp's context since they will use the same cmdbuf */ 203 context_VPP_p ctx; 204 int i; 205 206 ctx = (context_VPP_p) calloc(1, sizeof(struct context_VPP_s)); 207 if (NULL == ctx) { 208 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 209 DEBUG_FAILURE; 210 return vaStatus; 211 } 212 213 //set default VP8 sequence params 214 vsp_VP8_set_default_params(&ctx->vp8_seq_param); 215 ctx->temporal_layer_number = 1; 216 217 for (i = 0; i < obj_config->attrib_count; i++) { 218 if (obj_config->attrib_list[i].type == VAConfigAttribRateControl) { 219 if (obj_config->attrib_list[i].value == VA_RC_VCM) 220 ctx->vp8_seq_param.rc_end_usage = VP8_ENC_CBR_HRD; 221 else 222 ctx->vp8_seq_param.rc_end_usage = VP8_ENC_CBR; 223 } 224 } 225 226 /* set size */ 227 ctx->param_sz = 0; 228 ctx->pic_param_sz = ALIGN_TO_128(sizeof(struct VssVp8encPictureParameterBuffer)); 229 ctx->param_sz += ctx->pic_param_sz; 230 ctx->seq_param_sz = ALIGN_TO_128(sizeof(struct VssVp8encSequenceParameterBuffer)); 231 ctx->param_sz += ctx->seq_param_sz; 232 ctx->ref_param_sz = ALIGN_TO_128(sizeof(ref_frame_surface)); 233 ctx->param_sz += ctx->ref_param_sz; 234 235 /* set offset */ 236 ctx->pic_param_offset = 0; 237 ctx->seq_param_offset = ctx->pic_param_sz; 238 ctx->ref_param_offset = ctx->pic_param_sz + ctx->seq_param_sz; 239 240 241 ctx->context_buf = (psb_buffer_p) calloc(1, sizeof(struct psb_buffer_s)); 242 if (NULL == ctx->context_buf) { 243 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 244 DEBUG_FAILURE; 245 goto out; 246 } 247 248 vaStatus = psb_buffer_create(obj_context->driver_data, VSP_VP8ENC_STATE_SIZE, psb_bt_vpu_only, ctx->context_buf); 249 250 if (VA_STATUS_SUCCESS != vaStatus) { 251 goto out; 252 } 253 254 obj_context->format_data = (void*) ctx; 255 ctx->obj_context = obj_context; 256 257 return vaStatus; 258 259 out: 260 vsp_VP8_DestroyContext(obj_context); 261 262 if (ctx) { 263 if(ctx->context_buf != NULL) 264 free(ctx->context_buf); 265 free(ctx); 266 ctx = NULL; 267 } 268 269 return vaStatus; 270 } 271 272 static void vsp_VP8_DestroyContext( 273 object_context_p obj_context) 274 { 275 INIT_CONTEXT_VPP; 276 277 if (ctx->context_buf) { 278 psb_buffer_destroy(ctx->context_buf); 279 free(ctx->context_buf); 280 ctx->context_buf = NULL; 281 } 282 283 if (ctx->filters) { 284 free(ctx->filters); 285 ctx->num_filters = 0; 286 } 287 288 free(obj_context->format_data); 289 obj_context->format_data = NULL; 290 } 291 292 static VAStatus vsp_vp8_process_seqence_param( 293 psb_driver_data_p driver_data, 294 context_VPP_p ctx, 295 object_buffer_p obj_buffer) 296 { 297 298 VAStatus vaStatus = VA_STATUS_SUCCESS; 299 vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf; 300 int i; 301 int ref_frame_width, ref_frame_height, ref_chroma_height, ref_size; 302 303 VAEncSequenceParameterBufferVP8 *va_seq = 304 (VAEncSequenceParameterBufferVP8 *) obj_buffer->buffer_data; 305 struct VssVp8encSequenceParameterBuffer *seq = &ctx->vp8_seq_param; 306 struct VssVp8encSequenceParameterBuffer *seq_to_firmware = 307 (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p; 308 309 struct ref_frame_surface *ref = 310 (struct ref_frame_surface*)cmdbuf->ref_param_p; 311 312 seq->frame_width = va_seq->frame_width; 313 seq->frame_height = va_seq->frame_height; 314 seq->rc_target_bitrate = va_seq->bits_per_second / 1000; 315 seq->max_intra_rate = 100 * ctx->max_frame_size / 316 (va_seq->bits_per_second / seq->frame_rate); 317 /* FIXME: API doc says max 5000, but for current default test vector we still use 6000 */ 318 seq->kf_mode = va_seq->kf_auto; /* AUTO */ 319 seq->kf_max_dist = va_seq->kf_max_dist; 320 seq->kf_min_dist = va_seq->kf_min_dist; 321 seq->error_resilient = va_seq->error_resilient; 322 323 ref_frame_width = (seq->frame_width + 2 * 32 + 63) & (~63); 324 ref_frame_height = (seq->frame_height + 2 * 32 + 63) & (~63); 325 ref_chroma_height = (ref_frame_height / 2 + 63) & (~63); 326 ref_size = ref_frame_width * (ref_frame_height + ref_chroma_height); 327 328 for (i = 0; i < 4; i++) { 329 seq->ref_frame_buffers[i].surface_id = va_seq->reference_frames[i]; 330 seq->ref_frame_buffers[i].width = ref_frame_width; 331 seq->ref_frame_buffers[i].height = ref_frame_height; 332 } 333 334 for (i = 0; i < 4; i++) { 335 object_surface_p ref_surf = SURFACE(va_seq->reference_frames[i]); 336 if (!ref_surf) 337 return VA_STATUS_ERROR_UNKNOWN; 338 339 ref_surf->is_ref_surface = 2; 340 341 if (ref_surf->psb_surface->size < ref_size) { 342 /* re-alloc buffer */ 343 ref_surf->psb_surface->size = ref_size; 344 psb_buffer_destroy(&ref_surf->psb_surface->buf); 345 vaStatus = psb_buffer_create(driver_data, ref_surf->psb_surface->size, psb_bt_surface, &ref_surf->psb_surface->buf); 346 if (VA_STATUS_SUCCESS != vaStatus) 347 return VA_STATUS_ERROR_ALLOCATION_FAILED; 348 } 349 350 vsp_cmdbuf_reloc_pic_param(&(seq->ref_frame_buffers[i].base), 351 0, 352 &(ref_surf->psb_surface->buf), 353 cmdbuf->param_mem_loc, seq); 354 } 355 356 *seq_to_firmware = *seq; 357 358 vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VP8_ID, &cmdbuf->param_mem, 359 VssVp8encSetSequenceParametersCommand, 360 ctx->seq_param_offset, 361 sizeof(struct VssVp8encSequenceParameterBuffer)); 362 ctx->vp8_seq_cmd_send = 1; 363 364 return vaStatus; 365 } 366 367 static VAStatus vsp_vp8_process_dynamic_seqence_param( 368 context_VPP_p ctx) 369 { 370 371 VAStatus vaStatus = VA_STATUS_SUCCESS; 372 vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf; 373 int ref_frame_width, ref_frame_height; 374 375 struct VssVp8encSequenceParameterBuffer *seq = 376 (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p; 377 378 *seq = ctx->vp8_seq_param ; 379 seq->max_intra_rate = 100 * ctx->max_frame_size / 380 (seq->rc_target_bitrate * 1000 / seq->frame_rate); 381 382 if (!ctx->vp8_seq_cmd_send) { 383 vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VP8_ID, &cmdbuf->param_mem, 384 VssVp8encSetSequenceParametersCommand, 385 ctx->seq_param_offset, 386 sizeof(struct VssVp8encSequenceParameterBuffer)); 387 } 388 389 return vaStatus; 390 } 391 392 393 static VAStatus vsp_vp8_process_picture_param( 394 psb_driver_data_p driver_data, 395 context_VPP_p ctx, 396 object_buffer_p obj_buffer, 397 VASurfaceID surface_id) 398 399 { 400 VAStatus vaStatus = VA_STATUS_SUCCESS; 401 vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf; 402 403 VAEncPictureParameterBufferVP8 *va_pic = 404 (VAEncPictureParameterBufferVP8 *) obj_buffer->buffer_data; 405 struct VssVp8encPictureParameterBuffer *pic = 406 (struct VssVp8encPictureParameterBuffer *)cmdbuf->pic_param_p; 407 struct VssVp8encSequenceParameterBuffer *seq = 408 (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p; 409 int ref_frame_width, ref_frame_height; 410 vp8_fw_pic_flags flags; 411 412 ref_frame_width = (ctx->vp8_seq_param.frame_width + 2 * 32 + 63) & (~63); 413 ref_frame_height = (ctx->vp8_seq_param.frame_height + 2 * 32 + 63) & (~63); 414 415 //map parameters 416 object_buffer_p pObj = BUFFER(va_pic->coded_buf); //tobe modified 417 if (!pObj) 418 return VA_STATUS_ERROR_UNKNOWN; 419 420 object_surface_p src_surface = SURFACE(surface_id); 421 422 pic->input_frame.surface_id = surface_id; 423 pic->input_frame.irq = 1; 424 pic->input_frame.height = ctx->vp8_seq_param.frame_height; 425 pic->input_frame.width = ctx->vp8_seq_param.frame_width; 426 /* NOTE: In VIED API doc, stride must be the nearest integer multiple of 32 */ 427 /* use vaCreateSurfaceWithAttribute with VAExternalMemoryNULL to create surface*/ 428 //pic->input_frame.stride = (ctx->frame_width + 31) & (~31); 429 pic->input_frame.stride = ctx->obj_context->current_render_target->psb_surface->stride; 430 pic->input_frame.format = 0; /* TODO: Specify NV12 = 0 */ 431 432 pic->recon_frame.irq = 0; 433 pic->recon_frame.width = ref_frame_width; 434 pic->recon_frame.height = ref_frame_height; 435 436 pic->version = 0; 437 438 flags.value = 0; 439 flags.bits.force_kf = va_pic->ref_flags.bits.force_kf; 440 flags.bits.no_ref_last = va_pic->ref_flags.bits.no_ref_last; 441 flags.bits.no_ref_gf = va_pic->ref_flags.bits.no_ref_gf; 442 flags.bits.no_ref_arf = va_pic->ref_flags.bits.no_ref_arf; 443 flags.bits.upd_last = va_pic->pic_flags.bits.refresh_last; 444 flags.bits.upd_gf = va_pic->pic_flags.bits.copy_buffer_to_golden; 445 flags.bits.upd_arf = va_pic->pic_flags.bits.copy_buffer_to_alternate; 446 flags.bits.no_upd_last = !va_pic->pic_flags.bits.refresh_last; 447 flags.bits.no_upd_gf = !va_pic->pic_flags.bits.refresh_golden_frame; 448 flags.bits.no_upd_arf = !va_pic->pic_flags.bits.refresh_alternate_frame; 449 flags.bits.upd_entropy = va_pic->pic_flags.bits.refresh_entropy_probs; 450 if (ctx->temporal_layer_number > 1) 451 flags.bits.upd_entropy = 0; 452 pic->pic_flags = flags.value; 453 454 pic->prev_frame_dropped = 0; /* Not yet used */ 455 pic->cpuused = 5; 456 pic->sharpness = va_pic->sharpness_level; 457 pic->num_token_partitions = va_pic->pic_flags.bits.num_token_partitions; /* 2^2 = 4 partitions */ 458 pic->encoded_frame_size = pObj->size & ~31; 459 pic->encoded_frame_base = (uint32_t)pObj->buffer_data; 460 461 { 462 vsp_cmdbuf_reloc_pic_param(&(pic->encoded_frame_base), 463 ctx->pic_param_offset, pObj->psb_buffer, 464 cmdbuf->param_mem_loc, pic); 465 } 466 467 { 468 object_surface_p cur_surf = SURFACE(surface_id); 469 if (!cur_surf) 470 return VA_STATUS_ERROR_UNKNOWN; 471 472 vsp_cmdbuf_reloc_pic_param(&(pic->input_frame.base), 473 0, &(cur_surf->psb_surface->buf), 474 cmdbuf->param_mem_loc, pic); 475 vsp_cmdbuf_reloc_pic_param(&(pic->input_frame.base_uv), 476 pic->input_frame.stride * ctx->obj_context->current_render_target->height, 477 &(cur_surf->psb_surface->buf), 478 cmdbuf->param_mem_loc, pic); 479 } 480 481 *cmdbuf->cmd_idx++ = CONTEXT_VP8_ID; 482 *cmdbuf->cmd_idx++ = VssVp8encEncodeFrameCommand; 483 VSP_RELOC_CMDBUF(cmdbuf->cmd_idx++, ctx->pic_param_offset, &cmdbuf->param_mem); 484 *cmdbuf->cmd_idx++ = sizeof(struct VssVp8encPictureParameterBuffer); 485 *cmdbuf->cmd_idx++ = 0; 486 *cmdbuf->cmd_idx++ = 0; 487 *cmdbuf->cmd_idx++ = wsbmKBufHandle(wsbmKBuf(pObj->psb_buffer->drm_buf)) ; 488 *cmdbuf->cmd_idx++ = wsbmKBufHandle(wsbmKBuf((&cmdbuf->param_mem)->drm_buf)); 489 490 return vaStatus; 491 } 492 493 static VAStatus vsp_vp8_process_misc_param(context_VPP_p ctx, object_buffer_p obj_buffer) 494 { 495 VAEncMiscParameterBuffer *pBuffer; 496 VAEncMiscParameterAIR *air_param; 497 VAEncMiscParameterBufferMaxFrameSize *max_frame_size_param; 498 VAEncMiscParameterFrameRate *frame_rate_param; 499 VAEncMiscParameterRateControl *rate_control_param; 500 VAEncMiscParameterHRD *hrd_param; 501 VAEncMiscParameterTemporalLayerStructure* tslayer_param; 502 struct VssVp8encSequenceParameterBuffer *seq = &ctx->vp8_seq_param; 503 VAStatus vaStatus = VA_STATUS_SUCCESS; 504 uint32_t layer_id, i; 505 506 ASSERT(obj_buffer->type == VAEncMiscParameterBufferType); 507 pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data; 508 obj_buffer->size = 0; 509 510 switch (pBuffer->type) { 511 case VAEncMiscParameterTypeTemporalLayerStructure: 512 tslayer_param = (VAEncMiscParameterTemporalLayerStructure *)pBuffer->data; 513 //verify parameter 514 if (tslayer_param->number_of_layers < 2 && tslayer_param->number_of_layers > 3) { 515 drv_debug_msg(VIDEO_DEBUG_ERROR, "Temporal Layer Number should be 2 or 3\n"); 516 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 517 break; 518 } 519 520 if (tslayer_param->periodicity > 32 || tslayer_param->periodicity < 1) { 521 drv_debug_msg(VIDEO_DEBUG_ERROR, "ts_periodicity shoulde be 1 - 32\n"); 522 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 523 break; 524 } 525 526 for (i = 0; i < tslayer_param->periodicity; i++) { 527 layer_id = tslayer_param->layer_id[i]; 528 if (layer_id > (tslayer_param->number_of_layers - 1)) { 529 drv_debug_msg(VIDEO_DEBUG_ERROR, "layer_id shoulde be 0 - %d\n", 530 tslayer_param->number_of_layers - 1); 531 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 532 break; 533 } 534 } 535 536 if (vaStatus == VA_STATUS_ERROR_INVALID_PARAMETER) 537 break; 538 539 seq->ts_number_layers = tslayer_param->number_of_layers; 540 ctx->temporal_layer_number = tslayer_param->number_of_layers; 541 seq->ts_periodicity = tslayer_param->periodicity; 542 543 for (i = 0; i < seq->ts_periodicity; i++) 544 seq->ts_layer_id[i] = tslayer_param->layer_id[i]; 545 546 //set default bitrate and framerate 547 if (seq->ts_number_layers == 2) { 548 seq->ts_target_bitrate[0] = seq->rc_target_bitrate * 6 / 10; 549 seq->ts_target_bitrate[1] = seq->rc_target_bitrate ; 550 seq->ts_rate_decimator[0] = 2; 551 seq->ts_rate_decimator[1] = 1; 552 } 553 if (seq->ts_number_layers == 3) { 554 seq->ts_target_bitrate[0] = seq->rc_target_bitrate * 4 / 10; 555 seq->ts_target_bitrate[1] = seq->rc_target_bitrate * 6 / 10; 556 seq->ts_target_bitrate[2] = seq->rc_target_bitrate ; 557 seq->ts_rate_decimator[0] = 4; 558 seq->ts_rate_decimator[1] = 2; 559 seq->ts_rate_decimator[2] = 1; 560 } 561 562 ctx->re_send_seq_params = 1; 563 break; 564 case VAEncMiscParameterTypeFrameRate: 565 frame_rate_param = (VAEncMiscParameterFrameRate *)pBuffer->data; 566 if (frame_rate_param->framerate > 120) { 567 drv_debug_msg(VIDEO_DEBUG_ERROR, "%d is invalid." 568 "framerate could not be larger than 120\n", 569 frame_rate_param->framerate); 570 frame_rate_param->framerate = 120; 571 } 572 if (frame_rate_param->framerate < 1) { 573 drv_debug_msg(VIDEO_DEBUG_ERROR, "%d is invalid." 574 "framerate could not be smaller than 1\n", 575 frame_rate_param->framerate); 576 frame_rate_param->framerate = 1; 577 } 578 579 if (ctx->temporal_layer_number == 1) { 580 if (seq->frame_rate != frame_rate_param->framerate) { 581 drv_debug_msg(VIDEO_DEBUG_GENERAL, "frame rate changed from %d to %d\n", 582 seq->frame_rate, 583 frame_rate_param->framerate); 584 seq->frame_rate = frame_rate_param->framerate; 585 ctx->re_send_seq_params = 1; 586 } 587 } else { 588 layer_id = frame_rate_param->framerate_flags.bits.temporal_id % 3; 589 if (ctx->frame_rate[layer_id] != frame_rate_param->framerate) { 590 drv_debug_msg(VIDEO_DEBUG_GENERAL, "frame rate of layer %d will be changed from %d to %d\n", 591 layer_id, ctx->frame_rate[layer_id], frame_rate_param->framerate); 592 ctx->frame_rate[layer_id] = frame_rate_param->framerate; 593 if (layer_id == ctx->temporal_layer_number - 1) { //top layer 594 seq->frame_rate = ctx->frame_rate[layer_id]; 595 } 596 ctx->re_send_seq_params = 1 ; 597 } 598 } 599 break; 600 case VAEncMiscParameterTypeRateControl: 601 rate_control_param = (VAEncMiscParameterRateControl *)pBuffer->data; 602 if (rate_control_param->max_qp > 63 || 603 rate_control_param->min_qp > 63) { 604 drv_debug_msg(VIDEO_DEBUG_ERROR, "max_qp(%d) and min_qp(%d) " 605 "are invalid.\nQP shouldn't be larger than 63 for VP8\n", 606 rate_control_param->max_qp, rate_control_param->min_qp); 607 rate_control_param->max_qp = 63; 608 rate_control_param->min_qp = rate_control_param->max_qp; 609 } 610 611 if (rate_control_param->min_qp != seq->rc_min_quantizer) { 612 drv_debug_msg(VIDEO_DEBUG_ERROR, "min_qp was changed from %d to %d\n", 613 seq->rc_min_quantizer, rate_control_param->min_qp); 614 seq->rc_min_quantizer = rate_control_param->min_qp; 615 } 616 617 if (rate_control_param->max_qp != seq->rc_max_quantizer) { 618 drv_debug_msg(VIDEO_DEBUG_ERROR, "max_qp was changed from %d to %d\n", 619 seq->rc_max_quantizer, rate_control_param->max_qp); 620 seq->rc_max_quantizer = rate_control_param->max_qp; 621 } 622 623 // no initial qp for vp8 624 625 if (rate_control_param->target_percentage != seq->rc_undershoot_pct) { 626 drv_debug_msg(VIDEO_DEBUG_ERROR, "rc_undershoot was changed from %d to %d\n", 627 seq->rc_undershoot_pct, rate_control_param->target_percentage); 628 seq->rc_undershoot_pct = rate_control_param->target_percentage; 629 } 630 631 if (rate_control_param->bits_per_second / 1000 > 20000) { 632 drv_debug_msg(VIDEO_DEBUG_ERROR, "%d is invalid." 633 "bitrate could not be larger than 20000\n", 634 rate_control_param->bits_per_second / 1000); 635 rate_control_param->bits_per_second = 20000000; 636 } 637 638 if (ctx->temporal_layer_number == 1) { 639 if (rate_control_param->bits_per_second / 1000 != seq->rc_target_bitrate) { 640 drv_debug_msg(VIDEO_DEBUG_ERROR, "bitrate was changed from %dkbps to %dkbps\n", 641 seq->rc_target_bitrate, rate_control_param->bits_per_second / 1000); 642 seq->rc_target_bitrate = rate_control_param->bits_per_second / 1000; 643 seq->ts_target_bitrate[0] = rate_control_param->bits_per_second / 1000; 644 645 } 646 } else { 647 layer_id = rate_control_param->rc_flags.bits.temporal_id % 3; 648 if (rate_control_param->bits_per_second / 1000 != seq->ts_target_bitrate[layer_id]) { 649 drv_debug_msg(VIDEO_DEBUG_ERROR, "bitrate was changed from %dkbps to %dkbps\n", 650 seq->ts_target_bitrate[layer_id], rate_control_param->bits_per_second / 1000); 651 seq->ts_target_bitrate[layer_id] = rate_control_param->bits_per_second / 1000; 652 } 653 } 654 655 ctx->re_send_seq_params = 1; 656 break; 657 case VAEncMiscParameterTypeMaxFrameSize: 658 max_frame_size_param = (VAEncMiscParameterBufferMaxFrameSize *)pBuffer->data; 659 if (ctx->max_frame_size == max_frame_size_param->max_frame_size) 660 break; 661 662 drv_debug_msg(VIDEO_DEBUG_ERROR, "max frame size changed from %d to %d\n", 663 ctx->max_frame_size, max_frame_size_param->max_frame_size); 664 ctx->max_frame_size = max_frame_size_param->max_frame_size ; 665 ctx->re_send_seq_params = 1 ; 666 break; 667 case VAEncMiscParameterTypeAIR: 668 air_param = (VAEncMiscParameterAIR *)pBuffer->data; 669 if (air_param->air_num_mbs > 65535 || 670 air_param->air_threshold > 65535) { 671 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 672 break; 673 } 674 675 drv_debug_msg(VIDEO_DEBUG_GENERAL, "air slice size changed to num_air_mbs %d " 676 "air_threshold %d, air_auto %d\n", 677 air_param->air_num_mbs, air_param->air_threshold, 678 air_param->air_auto); 679 seq->cyclic_intra_refresh = air_param->air_threshold; 680 break; 681 case VAEncMiscParameterTypeHRD: 682 hrd_param = (VAEncMiscParameterHRD *)pBuffer->data; 683 seq->rc_buf_sz = hrd_param->buffer_size; 684 seq->rc_buf_initial_sz = hrd_param->initial_buffer_fullness; 685 seq->rc_buf_optimal_sz = hrd_param->optimal_buffer_fullness; 686 ctx->re_send_seq_params = 1; 687 break; 688 case VAEncMiscParameterTypeQualityLevel: 689 break; 690 691 default: 692 vaStatus = VA_STATUS_ERROR_UNKNOWN; 693 DEBUG_FAILURE; 694 break; 695 } 696 697 free(obj_buffer->buffer_data); 698 obj_buffer->buffer_data = NULL; 699 700 return vaStatus; 701 } 702 static VAStatus vsp_VP8_RenderPicture( 703 object_context_p obj_context, 704 object_buffer_p *buffers, 705 int num_buffers) 706 { 707 708 int i; 709 psb_driver_data_p driver_data = obj_context->driver_data; 710 INIT_CONTEXT_VPP; 711 VASurfaceID surface_id; 712 VAStatus vaStatus = VA_STATUS_SUCCESS; 713 714 for (i = 0; i < num_buffers; i++) { 715 716 object_buffer_p obj_buffer = buffers[i]; 717 switch (obj_buffer->type) { 718 case VAEncSequenceParameterBufferType: 719 vaStatus = vsp_vp8_process_seqence_param(driver_data, ctx, obj_buffer); 720 break; 721 case VAEncPictureParameterBufferType: 722 surface_id = obj_context->current_render_surface_id; 723 vaStatus = vsp_vp8_process_picture_param(driver_data, ctx, obj_buffer, surface_id); 724 break; 725 case VAEncMiscParameterBufferType: 726 vaStatus = vsp_vp8_process_misc_param(ctx, obj_buffer); 727 break; 728 default: 729 vaStatus = VA_STATUS_SUCCESS;//VA_STATUS_ERROR_UNKNOWN; 730 DEBUG_FAILURE; 731 } 732 733 if (vaStatus != VA_STATUS_SUCCESS) { 734 break; 735 } 736 } 737 738 return vaStatus; 739 } 740 741 static VAStatus vsp_VP8_BeginPicture( 742 object_context_p obj_context) 743 { 744 int ret; 745 VAStatus vaStatus = VA_STATUS_SUCCESS; 746 INIT_CONTEXT_VPP; 747 vsp_cmdbuf_p cmdbuf; 748 749 /* Initialise the command buffer */ 750 ret = vsp_context_get_next_cmdbuf(ctx->obj_context); 751 if (ret) { 752 drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n"); 753 vaStatus = VA_STATUS_ERROR_UNKNOWN; 754 return vaStatus; 755 } 756 757 cmdbuf = obj_context->vsp_cmdbuf; 758 759 if (ctx->obj_context->frame_count == 0) { /* first picture */ 760 vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VP8_ID, ctx->context_buf, Vss_Sys_STATE_BUF_COMMAND, 761 0, VSP_VP8ENC_STATE_SIZE); 762 } 763 764 /* map param mem */ 765 vaStatus = psb_buffer_map(&cmdbuf->param_mem, &cmdbuf->param_mem_p); 766 if (vaStatus) { 767 return vaStatus; 768 } 769 770 cmdbuf->pic_param_p = cmdbuf->param_mem_p; 771 cmdbuf->seq_param_p = cmdbuf->param_mem_p + ctx->seq_param_offset; 772 cmdbuf->ref_param_p = cmdbuf->param_mem_p + ctx->ref_param_offset; 773 ctx->vp8_seq_cmd_send = 0; 774 ctx->re_send_seq_params = 0; 775 776 return VA_STATUS_SUCCESS; 777 } 778 779 static inline void dump_vssporcPicture(struct VssProcPictureVP8 * frame) 780 { 781 drv_debug_msg(VIDEO_ENCODE_DEBUG, "surface_id 0x%08x\n", frame->surface_id); 782 drv_debug_msg(VIDEO_ENCODE_DEBUG, "irq %d\n", frame->irq); 783 drv_debug_msg(VIDEO_ENCODE_DEBUG, "base 0x%08x\n", frame->base); 784 drv_debug_msg(VIDEO_ENCODE_DEBUG, "base_uv 0x%08x\n", frame->base_uv); 785 drv_debug_msg(VIDEO_ENCODE_DEBUG, "height %d\n", frame->height); 786 drv_debug_msg(VIDEO_ENCODE_DEBUG, "width %d\n", frame->width); 787 drv_debug_msg(VIDEO_ENCODE_DEBUG, "stride %d\n", frame->stride); 788 drv_debug_msg(VIDEO_ENCODE_DEBUG, "format %d\n", frame->format); 789 } 790 791 static void vsp_vp8_dump_commands(vsp_cmdbuf_p cmdbuf) 792 { 793 unsigned int i, cmd_idx; 794 unsigned int cmdbuffer_size = (unsigned char *)cmdbuf->cmd_idx - cmdbuf->cmd_start; /* In bytes */ 795 unsigned int cmd_number = cmdbuffer_size / sizeof(struct vss_command_t); 796 struct vss_command_t *cmd = (struct vss_command_t *)cmdbuf->cmd_start; 797 struct VssVp8encPictureParameterBuffer *pic = 798 (struct VssVp8encPictureParameterBuffer *)cmdbuf->pic_param_p; 799 struct VssVp8encSequenceParameterBuffer *seq = 800 (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p; 801 802 for (cmd_idx = 0; cmd_idx < cmd_number; cmd_idx++) { 803 drv_debug_msg(VIDEO_ENCODE_DEBUG, "\n============command start============\ncontext %d\ntype%d\n", 804 cmd[cmd_idx].context, cmd[cmd_idx].type); 805 if (cmd[cmd_idx].type == VssVp8encEncodeFrameCommand) { 806 drv_debug_msg(VIDEO_ENCODE_DEBUG, "input frame\n"); 807 dump_vssporcPicture(&pic->input_frame); 808 809 drv_debug_msg(VIDEO_ENCODE_DEBUG, "recon frame\n"); 810 dump_vssporcPicture(&pic->recon_frame); 811 812 drv_debug_msg(VIDEO_ENCODE_DEBUG, "version %d\n", pic->version); 813 drv_debug_msg(VIDEO_ENCODE_DEBUG, "pic_flags 0x%08x\n", pic->pic_flags); 814 drv_debug_msg(VIDEO_ENCODE_DEBUG, "prev_frame_dropped %d\n", pic->prev_frame_dropped); 815 drv_debug_msg(VIDEO_ENCODE_DEBUG, "cpuused %d\n", pic->cpuused); 816 drv_debug_msg(VIDEO_ENCODE_DEBUG, "sharpness %d\n", pic->sharpness); 817 drv_debug_msg(VIDEO_ENCODE_DEBUG, "num_token_partitions %d\n", pic->num_token_partitions); 818 drv_debug_msg(VIDEO_ENCODE_DEBUG, "encoded_frame_size %d\n", pic->encoded_frame_size); 819 drv_debug_msg(VIDEO_ENCODE_DEBUG, "encoded_frame_base 0x%08x\n", pic->encoded_frame_base); 820 } 821 822 if (cmd[cmd_idx].type == VssVp8encSetSequenceParametersCommand) { 823 drv_debug_msg(VIDEO_ENCODE_DEBUG, "frame_width %d\n", seq->frame_width); 824 drv_debug_msg(VIDEO_ENCODE_DEBUG, "frame_height %d\n", seq->frame_height); 825 drv_debug_msg(VIDEO_ENCODE_DEBUG, "frame_rate %d\n", seq->frame_rate); 826 drv_debug_msg(VIDEO_ENCODE_DEBUG, "error_resilient %d\n", seq->error_resilient); 827 drv_debug_msg(VIDEO_ENCODE_DEBUG, "num_token_partitions %d\n", seq->num_token_partitions); 828 drv_debug_msg(VIDEO_ENCODE_DEBUG, "kf_mode %d\n", seq->kf_mode); 829 drv_debug_msg(VIDEO_ENCODE_DEBUG, "kf_min_dist %d\n", seq->kf_min_dist); 830 drv_debug_msg(VIDEO_ENCODE_DEBUG, "kf_max_dist %d\n", seq->kf_max_dist); 831 drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_target_bitrate %d\n", seq->rc_target_bitrate); 832 drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_min_quantizer %d\n", seq->rc_min_quantizer); 833 drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_max_quantizer %d\n", seq->rc_max_quantizer); 834 drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_undershoot_pct %d\n", seq->rc_undershoot_pct); 835 drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_overshoot_pct %d\n", seq->rc_overshoot_pct); 836 drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_end_usage %d\n", seq->rc_end_usage); 837 drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_buf_sz %d\n", seq->rc_buf_sz); 838 drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_buf_initial_sz %d\n", seq->rc_buf_initial_sz); 839 drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_buf_optimal_sz %d\n", seq->rc_buf_optimal_sz); 840 drv_debug_msg(VIDEO_ENCODE_DEBUG, "max_intra_rate %d\n", seq->max_intra_rate); 841 drv_debug_msg(VIDEO_ENCODE_DEBUG, "cyclic_intra_refresh %d\n", seq->cyclic_intra_refresh); 842 drv_debug_msg(VIDEO_ENCODE_DEBUG, "concatenate_partitions %d\n", seq->concatenate_partitions); 843 drv_debug_msg(VIDEO_ENCODE_DEBUG, "recon_buffer_mode %d\n", seq->recon_buffer_mode); 844 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ts_number_layers %d\n", seq->ts_number_layers); 845 846 for (i = 0; i < 3; i++) 847 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ts_target_bitrate[%d] %d\n", i, seq->ts_target_bitrate[i]); 848 849 for (i = 0; i < 3; i++) 850 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ts_rate_decimator[%d] %d\n", i, seq->ts_rate_decimator[i]); 851 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ts_periodicity %d\n", seq->ts_periodicity); 852 853 for (i = 0; i < seq->ts_periodicity; i++) 854 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ts_layer_id[%d] %d\n", i, seq->ts_layer_id[i]); 855 856 for (i = 0; i < 4; i++) { 857 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ref_frame_buffer %d\n", i); 858 dump_vssporcPicture(&seq->ref_frame_buffers[i]); 859 } 860 } 861 862 drv_debug_msg(VIDEO_ENCODE_DEBUG, "============command end============\n"); 863 } 864 } 865 866 867 static VAStatus vsp_VP8_EndPicture( 868 object_context_p obj_context) 869 { 870 INIT_CONTEXT_VPP; 871 psb_driver_data_p driver_data = obj_context->driver_data; 872 vsp_cmdbuf_p cmdbuf = obj_context->vsp_cmdbuf; 873 874 if (ctx->re_send_seq_params) { 875 vsp_vp8_process_dynamic_seqence_param(ctx); 876 } 877 878 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ctx->obj_context->frame_count=%d\n", ctx->obj_context->frame_count + 1); 879 vsp_vp8_dump_commands(cmdbuf); 880 881 if (cmdbuf->param_mem_p != NULL) { 882 psb_buffer_unmap(&cmdbuf->param_mem); 883 cmdbuf->param_mem_p = NULL; 884 cmdbuf->pic_param_p = NULL; 885 cmdbuf->end_param_p = NULL; 886 cmdbuf->pipeline_param_p = NULL; 887 cmdbuf->denoise_param_p = NULL; 888 cmdbuf->enhancer_param_p = NULL; 889 cmdbuf->sharpen_param_p = NULL; 890 cmdbuf->frc_param_p = NULL; 891 cmdbuf->ref_param_p = NULL; 892 } 893 894 if (vsp_context_flush_cmdbuf(ctx->obj_context)) { 895 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_VP8: flush deblock cmdbuf error\n"); 896 return VA_STATUS_ERROR_UNKNOWN; 897 } 898 899 return VA_STATUS_SUCCESS; 900 } 901 902 struct format_vtable_s vsp_VP8_vtable = { 903 queryConfigAttributes: 904 vsp_VP8_QueryConfigAttributes, 905 validateConfig: 906 vsp_VP8_ValidateConfig, 907 createContext: 908 vsp_VP8_CreateContext, 909 destroyContext: 910 vsp_VP8_DestroyContext, 911 beginPicture: 912 vsp_VP8_BeginPicture, 913 renderPicture: 914 vsp_VP8_RenderPicture, 915 endPicture: 916 vsp_VP8_EndPicture 917 }; 918