1 /************************************************************************** 2 * 3 * Copyright 2010 Thomas Balling Srensen & Orasanu Lucian. 4 * Copyright 2014 Advanced Micro Devices, Inc. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29 #include "pipe/p_video_codec.h" 30 31 #include "util/u_handle_table.h" 32 #include "util/u_video.h" 33 34 #include "vl/vl_vlc.h" 35 #include "vl/vl_winsys.h" 36 37 #include "va_private.h" 38 39 VAStatus 40 vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID render_target) 41 { 42 vlVaDriver *drv; 43 vlVaContext *context; 44 vlVaSurface *surf; 45 46 if (!ctx) 47 return VA_STATUS_ERROR_INVALID_CONTEXT; 48 49 drv = VL_VA_DRIVER(ctx); 50 if (!drv) 51 return VA_STATUS_ERROR_INVALID_CONTEXT; 52 53 pipe_mutex_lock(drv->mutex); 54 context = handle_table_get(drv->htab, context_id); 55 if (!context) { 56 pipe_mutex_unlock(drv->mutex); 57 return VA_STATUS_ERROR_INVALID_CONTEXT; 58 } 59 60 surf = handle_table_get(drv->htab, render_target); 61 pipe_mutex_unlock(drv->mutex); 62 if (!surf || !surf->buffer) 63 return VA_STATUS_ERROR_INVALID_SURFACE; 64 65 context->target_id = render_target; 66 surf->ctx = context_id; 67 context->target = surf->buffer; 68 69 if (!context->decoder) { 70 71 /* VPP */ 72 if (context->templat.profile == PIPE_VIDEO_PROFILE_UNKNOWN && 73 context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM && 74 context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM && 75 context->target->buffer_format != PIPE_FORMAT_B8G8R8X8_UNORM && 76 context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM && 77 context->target->buffer_format != PIPE_FORMAT_NV12) 78 return VA_STATUS_ERROR_UNIMPLEMENTED; 79 80 return VA_STATUS_SUCCESS; 81 } 82 83 if (context->decoder->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) 84 context->needs_begin_frame = true; 85 86 return VA_STATUS_SUCCESS; 87 } 88 89 void 90 vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, 91 struct pipe_video_buffer **ref_frame) 92 { 93 vlVaSurface *surf = handle_table_get(drv->htab, surface_id); 94 if (surf) 95 *ref_frame = surf->buffer; 96 else 97 *ref_frame = NULL; 98 } 99 100 static void 101 getEncParamPreset(vlVaContext *context) 102 { 103 //motion estimation preset 104 context->desc.h264enc.motion_est.motion_est_quarter_pixel = 0x00000001; 105 context->desc.h264enc.motion_est.lsmvert = 0x00000002; 106 context->desc.h264enc.motion_est.enc_disable_sub_mode = 0x00000078; 107 context->desc.h264enc.motion_est.enc_en_ime_overw_dis_subm = 0x00000001; 108 context->desc.h264enc.motion_est.enc_ime_overw_dis_subm_no = 0x00000001; 109 context->desc.h264enc.motion_est.enc_ime2_search_range_x = 0x00000004; 110 context->desc.h264enc.motion_est.enc_ime2_search_range_y = 0x00000004; 111 112 //pic control preset 113 context->desc.h264enc.pic_ctrl.enc_cabac_enable = 0x00000001; 114 context->desc.h264enc.pic_ctrl.enc_constraint_set_flags = 0x00000040; 115 116 //rate control 117 context->desc.h264enc.rate_ctrl.vbv_buffer_size = 20000000; 118 context->desc.h264enc.rate_ctrl.vbv_buf_lv = 48; 119 context->desc.h264enc.rate_ctrl.fill_data_enable = 1; 120 context->desc.h264enc.rate_ctrl.enforce_hrd = 1; 121 context->desc.h264enc.enable_vui = false; 122 if (context->desc.h264enc.rate_ctrl.frame_rate_num == 0) 123 context->desc.h264enc.rate_ctrl.frame_rate_num = 30; 124 context->desc.h264enc.rate_ctrl.target_bits_picture = 125 context->desc.h264enc.rate_ctrl.target_bitrate / context->desc.h264enc.rate_ctrl.frame_rate_num; 126 context->desc.h264enc.rate_ctrl.peak_bits_picture_integer = 127 context->desc.h264enc.rate_ctrl.peak_bitrate / context->desc.h264enc.rate_ctrl.frame_rate_num; 128 context->desc.h264enc.rate_ctrl.peak_bits_picture_fraction = 0; 129 130 context->desc.h264enc.ref_pic_mode = 0x00000201; 131 } 132 133 static VAStatus 134 handlePictureParameterBuffer(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 135 { 136 VAStatus vaStatus = VA_STATUS_SUCCESS; 137 138 switch (u_reduce_video_profile(context->templat.profile)) { 139 case PIPE_VIDEO_FORMAT_MPEG12: 140 vlVaHandlePictureParameterBufferMPEG12(drv, context, buf); 141 break; 142 143 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 144 vlVaHandlePictureParameterBufferH264(drv, context, buf); 145 break; 146 147 case PIPE_VIDEO_FORMAT_VC1: 148 vlVaHandlePictureParameterBufferVC1(drv, context, buf); 149 break; 150 151 case PIPE_VIDEO_FORMAT_MPEG4: 152 vlVaHandlePictureParameterBufferMPEG4(drv, context, buf); 153 break; 154 155 case PIPE_VIDEO_FORMAT_HEVC: 156 vlVaHandlePictureParameterBufferHEVC(drv, context, buf); 157 break; 158 159 default: 160 break; 161 } 162 163 /* Create the decoder once max_references is known. */ 164 if (!context->decoder) { 165 if (!context->target) 166 return VA_STATUS_ERROR_INVALID_CONTEXT; 167 168 if (context->templat.max_references == 0) 169 return VA_STATUS_ERROR_INVALID_BUFFER; 170 171 if (u_reduce_video_profile(context->templat.profile) == 172 PIPE_VIDEO_FORMAT_MPEG4_AVC) 173 context->templat.level = u_get_h264_level(context->templat.width, 174 context->templat.height, &context->templat.max_references); 175 176 context->decoder = drv->pipe->create_video_codec(drv->pipe, 177 &context->templat); 178 179 if (!context->decoder) 180 return VA_STATUS_ERROR_ALLOCATION_FAILED; 181 182 context->needs_begin_frame = true; 183 } 184 185 return vaStatus; 186 } 187 188 static void 189 handleIQMatrixBuffer(vlVaContext *context, vlVaBuffer *buf) 190 { 191 switch (u_reduce_video_profile(context->templat.profile)) { 192 case PIPE_VIDEO_FORMAT_MPEG12: 193 vlVaHandleIQMatrixBufferMPEG12(context, buf); 194 break; 195 196 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 197 vlVaHandleIQMatrixBufferH264(context, buf); 198 break; 199 200 case PIPE_VIDEO_FORMAT_MPEG4: 201 vlVaHandleIQMatrixBufferMPEG4(context, buf); 202 break; 203 204 case PIPE_VIDEO_FORMAT_HEVC: 205 vlVaHandleIQMatrixBufferHEVC(context, buf); 206 break; 207 208 default: 209 break; 210 } 211 } 212 213 static void 214 handleSliceParameterBuffer(vlVaContext *context, vlVaBuffer *buf) 215 { 216 switch (u_reduce_video_profile(context->templat.profile)) { 217 case PIPE_VIDEO_FORMAT_MPEG12: 218 vlVaHandleSliceParameterBufferMPEG12(context, buf); 219 break; 220 221 case PIPE_VIDEO_FORMAT_VC1: 222 vlVaHandleSliceParameterBufferVC1(context, buf); 223 break; 224 225 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 226 vlVaHandleSliceParameterBufferH264(context, buf); 227 break; 228 229 case PIPE_VIDEO_FORMAT_MPEG4: 230 vlVaHandleSliceParameterBufferMPEG4(context, buf); 231 break; 232 233 case PIPE_VIDEO_FORMAT_HEVC: 234 vlVaHandleSliceParameterBufferHEVC(context, buf); 235 break; 236 237 default: 238 break; 239 } 240 } 241 242 static unsigned int 243 bufHasStartcode(vlVaBuffer *buf, unsigned int code, unsigned int bits) 244 { 245 struct vl_vlc vlc = {0}; 246 int i; 247 248 /* search the first 64 bytes for a startcode */ 249 vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, &buf->size); 250 for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= bits; ++i) { 251 if (vl_vlc_peekbits(&vlc, bits) == code) 252 return 1; 253 vl_vlc_eatbits(&vlc, 8); 254 vl_vlc_fillbits(&vlc); 255 } 256 257 return 0; 258 } 259 260 static void 261 handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) 262 { 263 enum pipe_video_format format; 264 unsigned num_buffers = 0; 265 void * const *buffers[2]; 266 unsigned sizes[2]; 267 static const uint8_t start_code_h264[] = { 0x00, 0x00, 0x01 }; 268 static const uint8_t start_code_h265[] = { 0x00, 0x00, 0x01 }; 269 static const uint8_t start_code_vc1[] = { 0x00, 0x00, 0x01, 0x0d }; 270 271 format = u_reduce_video_profile(context->templat.profile); 272 switch (format) { 273 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 274 if (bufHasStartcode(buf, 0x000001, 24)) 275 break; 276 277 buffers[num_buffers] = (void *const)&start_code_h264; 278 sizes[num_buffers++] = sizeof(start_code_h264); 279 break; 280 case PIPE_VIDEO_FORMAT_HEVC: 281 if (bufHasStartcode(buf, 0x000001, 24)) 282 break; 283 284 buffers[num_buffers] = (void *const)&start_code_h265; 285 sizes[num_buffers++] = sizeof(start_code_h265); 286 break; 287 case PIPE_VIDEO_FORMAT_VC1: 288 if (bufHasStartcode(buf, 0x0000010d, 32) || 289 bufHasStartcode(buf, 0x0000010c, 32) || 290 bufHasStartcode(buf, 0x0000010b, 32)) 291 break; 292 293 if (context->decoder->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) { 294 buffers[num_buffers] = (void *const)&start_code_vc1; 295 sizes[num_buffers++] = sizeof(start_code_vc1); 296 } 297 break; 298 case PIPE_VIDEO_FORMAT_MPEG4: 299 if (bufHasStartcode(buf, 0x000001, 24)) 300 break; 301 302 vlVaDecoderFixMPEG4Startcode(context); 303 buffers[num_buffers] = (void *)context->mpeg4.start_code; 304 sizes[num_buffers++] = context->mpeg4.start_code_size; 305 default: 306 break; 307 } 308 309 buffers[num_buffers] = buf->data; 310 sizes[num_buffers] = buf->size; 311 ++num_buffers; 312 313 if (context->needs_begin_frame) { 314 context->decoder->begin_frame(context->decoder, context->target, 315 &context->desc.base); 316 context->needs_begin_frame = false; 317 } 318 context->decoder->decode_bitstream(context->decoder, context->target, &context->desc.base, 319 num_buffers, (const void * const*)buffers, sizes); 320 } 321 322 static VAStatus 323 handleVAEncMiscParameterTypeRateControl(vlVaContext *context, VAEncMiscParameterBuffer *misc) 324 { 325 VAEncMiscParameterRateControl *rc = (VAEncMiscParameterRateControl *)misc->data; 326 if (context->desc.h264enc.rate_ctrl.rate_ctrl_method == 327 PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT) 328 context->desc.h264enc.rate_ctrl.target_bitrate = rc->bits_per_second; 329 else 330 context->desc.h264enc.rate_ctrl.target_bitrate = rc->bits_per_second * (rc->target_percentage / 100.0); 331 context->desc.h264enc.rate_ctrl.peak_bitrate = rc->bits_per_second; 332 if (context->desc.h264enc.rate_ctrl.target_bitrate < 2000000) 333 context->desc.h264enc.rate_ctrl.vbv_buffer_size = MIN2((context->desc.h264enc.rate_ctrl.target_bitrate * 2.75), 2000000); 334 else 335 context->desc.h264enc.rate_ctrl.vbv_buffer_size = context->desc.h264enc.rate_ctrl.target_bitrate; 336 337 return VA_STATUS_SUCCESS; 338 } 339 340 static VAStatus 341 handleVAEncMiscParameterTypeFrameRate(vlVaContext *context, VAEncMiscParameterBuffer *misc) 342 { 343 VAEncMiscParameterFrameRate *fr = (VAEncMiscParameterFrameRate *)misc->data; 344 context->desc.h264enc.rate_ctrl.frame_rate_num = fr->framerate; 345 return VA_STATUS_SUCCESS; 346 } 347 348 static VAStatus 349 handleVAEncSequenceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 350 { 351 VAEncSequenceParameterBufferH264 *h264 = (VAEncSequenceParameterBufferH264 *)buf->data; 352 if (!context->decoder) { 353 context->templat.max_references = h264->max_num_ref_frames; 354 context->templat.level = h264->level_idc; 355 context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat); 356 if (!context->decoder) 357 return VA_STATUS_ERROR_ALLOCATION_FAILED; 358 } 359 360 context->gop_coeff = ((1024 + h264->intra_idr_period - 1) / h264->intra_idr_period + 1) / 2 * 2; 361 if (context->gop_coeff > VL_VA_ENC_GOP_COEFF) 362 context->gop_coeff = VL_VA_ENC_GOP_COEFF; 363 context->desc.h264enc.gop_size = h264->intra_idr_period * context->gop_coeff; 364 context->desc.h264enc.rate_ctrl.frame_rate_num = h264->time_scale / 2; 365 context->desc.h264enc.rate_ctrl.frame_rate_den = 1; 366 return VA_STATUS_SUCCESS; 367 } 368 369 static VAStatus 370 handleVAEncMiscParameterBufferType(vlVaContext *context, vlVaBuffer *buf) 371 { 372 VAStatus vaStatus = VA_STATUS_SUCCESS; 373 VAEncMiscParameterBuffer *misc; 374 misc = buf->data; 375 376 switch (misc->type) { 377 case VAEncMiscParameterTypeRateControl: 378 vaStatus = handleVAEncMiscParameterTypeRateControl(context, misc); 379 break; 380 381 case VAEncMiscParameterTypeFrameRate: 382 vaStatus = handleVAEncMiscParameterTypeFrameRate(context, misc); 383 break; 384 385 default: 386 break; 387 } 388 389 return vaStatus; 390 } 391 392 static VAStatus 393 handleVAEncPictureParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 394 { 395 VAEncPictureParameterBufferH264 *h264; 396 vlVaBuffer *coded_buf; 397 398 h264 = buf->data; 399 context->desc.h264enc.frame_num = h264->frame_num; 400 context->desc.h264enc.not_referenced = false; 401 context->desc.h264enc.is_idr = (h264->pic_fields.bits.idr_pic_flag == 1); 402 context->desc.h264enc.pic_order_cnt = h264->CurrPic.TopFieldOrderCnt; 403 if (context->desc.h264enc.gop_cnt == 0) 404 context->desc.h264enc.i_remain = context->gop_coeff; 405 else if (context->desc.h264enc.frame_num == 1) 406 context->desc.h264enc.i_remain--; 407 408 context->desc.h264enc.p_remain = context->desc.h264enc.gop_size - context->desc.h264enc.gop_cnt - context->desc.h264enc.i_remain; 409 410 coded_buf = handle_table_get(drv->htab, h264->coded_buf); 411 if (!coded_buf->derived_surface.resource) 412 coded_buf->derived_surface.resource = pipe_buffer_create(drv->pipe->screen, PIPE_BIND_VERTEX_BUFFER, 413 PIPE_USAGE_STREAM, coded_buf->size); 414 context->coded_buf = coded_buf; 415 416 context->desc.h264enc.frame_idx[h264->CurrPic.picture_id] = h264->frame_num; 417 if (context->desc.h264enc.is_idr) 418 context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; 419 else 420 context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; 421 422 context->desc.h264enc.quant_i_frames = h264->pic_init_qp; 423 context->desc.h264enc.quant_b_frames = h264->pic_init_qp; 424 context->desc.h264enc.quant_p_frames = h264->pic_init_qp; 425 context->desc.h264enc.gop_cnt++; 426 if (context->desc.h264enc.gop_cnt == context->desc.h264enc.gop_size) 427 context->desc.h264enc.gop_cnt = 0; 428 429 return VA_STATUS_SUCCESS; 430 } 431 432 static VAStatus 433 handleVAEncSliceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 434 { 435 VAEncSliceParameterBufferH264 *h264; 436 437 h264 = buf->data; 438 context->desc.h264enc.ref_idx_l0 = VA_INVALID_ID; 439 context->desc.h264enc.ref_idx_l1 = VA_INVALID_ID; 440 441 for (int i = 0; i < 32; i++) { 442 if (h264->RefPicList0[i].picture_id != VA_INVALID_ID) { 443 if (context->desc.h264enc.ref_idx_l0 == VA_INVALID_ID) 444 context->desc.h264enc.ref_idx_l0 = context->desc.h264enc.frame_idx[h264->RefPicList0[i].picture_id]; 445 } 446 if (h264->RefPicList1[i].picture_id != VA_INVALID_ID && h264->slice_type == 1) { 447 if (context->desc.h264enc.ref_idx_l1 == VA_INVALID_ID) 448 context->desc.h264enc.ref_idx_l1 = context->desc.h264enc.frame_idx[h264->RefPicList1[i].picture_id]; 449 } 450 } 451 452 if (h264->slice_type == 1) 453 context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; 454 else if (h264->slice_type == 0) 455 context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; 456 else if (h264->slice_type == 2) { 457 if (context->desc.h264enc.is_idr){ 458 context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; 459 context->desc.h264enc.idr_pic_id++; 460 } else 461 context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_I; 462 } else 463 context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_SKIP; 464 465 return VA_STATUS_SUCCESS; 466 } 467 468 VAStatus 469 vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buffers, int num_buffers) 470 { 471 vlVaDriver *drv; 472 vlVaContext *context; 473 VAStatus vaStatus = VA_STATUS_SUCCESS; 474 475 unsigned i; 476 477 if (!ctx) 478 return VA_STATUS_ERROR_INVALID_CONTEXT; 479 480 drv = VL_VA_DRIVER(ctx); 481 if (!drv) 482 return VA_STATUS_ERROR_INVALID_CONTEXT; 483 484 pipe_mutex_lock(drv->mutex); 485 context = handle_table_get(drv->htab, context_id); 486 if (!context) { 487 pipe_mutex_unlock(drv->mutex); 488 return VA_STATUS_ERROR_INVALID_CONTEXT; 489 } 490 491 for (i = 0; i < num_buffers; ++i) { 492 vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]); 493 if (!buf) { 494 pipe_mutex_unlock(drv->mutex); 495 return VA_STATUS_ERROR_INVALID_BUFFER; 496 } 497 498 switch (buf->type) { 499 case VAPictureParameterBufferType: 500 vaStatus = handlePictureParameterBuffer(drv, context, buf); 501 break; 502 503 case VAIQMatrixBufferType: 504 handleIQMatrixBuffer(context, buf); 505 break; 506 507 case VASliceParameterBufferType: 508 handleSliceParameterBuffer(context, buf); 509 break; 510 511 case VASliceDataBufferType: 512 handleVASliceDataBufferType(context, buf); 513 break; 514 case VAProcPipelineParameterBufferType: 515 vaStatus = vlVaHandleVAProcPipelineParameterBufferType(drv, context, buf); 516 break; 517 518 case VAEncSequenceParameterBufferType: 519 vaStatus = handleVAEncSequenceParameterBufferType(drv, context, buf); 520 break; 521 522 case VAEncMiscParameterBufferType: 523 vaStatus = handleVAEncMiscParameterBufferType(context, buf); 524 break; 525 526 case VAEncPictureParameterBufferType: 527 vaStatus = handleVAEncPictureParameterBufferType(drv, context, buf); 528 break; 529 530 case VAEncSliceParameterBufferType: 531 vaStatus = handleVAEncSliceParameterBufferType(drv, context, buf); 532 break; 533 534 default: 535 break; 536 } 537 } 538 pipe_mutex_unlock(drv->mutex); 539 540 return vaStatus; 541 } 542 543 VAStatus 544 vlVaEndPicture(VADriverContextP ctx, VAContextID context_id) 545 { 546 vlVaDriver *drv; 547 vlVaContext *context; 548 vlVaBuffer *coded_buf; 549 vlVaSurface *surf; 550 void *feedback; 551 552 if (!ctx) 553 return VA_STATUS_ERROR_INVALID_CONTEXT; 554 555 drv = VL_VA_DRIVER(ctx); 556 if (!drv) 557 return VA_STATUS_ERROR_INVALID_CONTEXT; 558 559 pipe_mutex_lock(drv->mutex); 560 context = handle_table_get(drv->htab, context_id); 561 pipe_mutex_unlock(drv->mutex); 562 if (!context) 563 return VA_STATUS_ERROR_INVALID_CONTEXT; 564 565 if (!context->decoder) { 566 if (context->templat.profile != PIPE_VIDEO_PROFILE_UNKNOWN) 567 return VA_STATUS_ERROR_INVALID_CONTEXT; 568 569 /* VPP */ 570 return VA_STATUS_SUCCESS; 571 } 572 573 pipe_mutex_lock(drv->mutex); 574 surf = handle_table_get(drv->htab, context->target_id); 575 context->mpeg4.frame_num++; 576 577 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 578 coded_buf = context->coded_buf; 579 getEncParamPreset(context); 580 context->desc.h264enc.frame_num_cnt++; 581 context->decoder->begin_frame(context->decoder, context->target, &context->desc.base); 582 context->decoder->encode_bitstream(context->decoder, context->target, 583 coded_buf->derived_surface.resource, &feedback); 584 surf->feedback = feedback; 585 surf->coded_buf = coded_buf; 586 } 587 588 context->decoder->end_frame(context->decoder, context->target, &context->desc.base); 589 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 590 int idr_period = context->desc.h264enc.gop_size / context->gop_coeff; 591 int p_remain_in_idr = idr_period - context->desc.h264enc.frame_num; 592 surf->frame_num_cnt = context->desc.h264enc.frame_num_cnt; 593 surf->force_flushed = false; 594 if (context->first_single_submitted) { 595 context->decoder->flush(context->decoder); 596 context->first_single_submitted = false; 597 surf->force_flushed = true; 598 } 599 if (p_remain_in_idr == 1) { 600 if ((context->desc.h264enc.frame_num_cnt % 2) != 0) { 601 context->decoder->flush(context->decoder); 602 context->first_single_submitted = true; 603 } 604 else 605 context->first_single_submitted = false; 606 surf->force_flushed = true; 607 } 608 } 609 pipe_mutex_unlock(drv->mutex); 610 return VA_STATUS_SUCCESS; 611 } 612