picture.c revision 7ec681f3
1/************************************************************************** 2 * 3 * Copyright 2010 Thomas Balling Sørensen & 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#include "util/u_memory.h" 34 35#include "vl/vl_vlc.h" 36#include "vl/vl_winsys.h" 37 38#include "va_private.h" 39 40VAStatus 41vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID render_target) 42{ 43 vlVaDriver *drv; 44 vlVaContext *context; 45 vlVaSurface *surf; 46 47 if (!ctx) 48 return VA_STATUS_ERROR_INVALID_CONTEXT; 49 50 drv = VL_VA_DRIVER(ctx); 51 if (!drv) 52 return VA_STATUS_ERROR_INVALID_CONTEXT; 53 54 mtx_lock(&drv->mutex); 55 context = handle_table_get(drv->htab, context_id); 56 if (!context) { 57 mtx_unlock(&drv->mutex); 58 return VA_STATUS_ERROR_INVALID_CONTEXT; 59 } 60 61 if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG12) { 62 context->desc.mpeg12.intra_matrix = NULL; 63 context->desc.mpeg12.non_intra_matrix = NULL; 64 } 65 66 surf = handle_table_get(drv->htab, render_target); 67 mtx_unlock(&drv->mutex); 68 if (!surf || !surf->buffer) 69 return VA_STATUS_ERROR_INVALID_SURFACE; 70 71 context->target_id = render_target; 72 surf->ctx = context_id; 73 context->target = surf->buffer; 74 context->mjpeg.sampling_factor = 0; 75 76 if (!context->decoder) { 77 78 /* VPP */ 79 if (context->templat.profile == PIPE_VIDEO_PROFILE_UNKNOWN && 80 context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM && 81 context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM && 82 context->target->buffer_format != PIPE_FORMAT_B8G8R8X8_UNORM && 83 context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM && 84 context->target->buffer_format != PIPE_FORMAT_NV12 && 85 context->target->buffer_format != PIPE_FORMAT_P010 && 86 context->target->buffer_format != PIPE_FORMAT_P016) 87 return VA_STATUS_ERROR_UNIMPLEMENTED; 88 89 return VA_STATUS_SUCCESS; 90 } 91 92 if (context->decoder->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) 93 context->needs_begin_frame = true; 94 95 return VA_STATUS_SUCCESS; 96} 97 98void 99vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, 100 struct pipe_video_buffer **ref_frame) 101{ 102 vlVaSurface *surf = handle_table_get(drv->htab, surface_id); 103 if (surf) 104 *ref_frame = surf->buffer; 105 else 106 *ref_frame = NULL; 107} 108 109static VAStatus 110handlePictureParameterBuffer(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 111{ 112 VAStatus vaStatus = VA_STATUS_SUCCESS; 113 enum pipe_video_format format = 114 u_reduce_video_profile(context->templat.profile); 115 116 switch (format) { 117 case PIPE_VIDEO_FORMAT_MPEG12: 118 vlVaHandlePictureParameterBufferMPEG12(drv, context, buf); 119 break; 120 121 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 122 vlVaHandlePictureParameterBufferH264(drv, context, buf); 123 break; 124 125 case PIPE_VIDEO_FORMAT_VC1: 126 vlVaHandlePictureParameterBufferVC1(drv, context, buf); 127 break; 128 129 case PIPE_VIDEO_FORMAT_MPEG4: 130 vlVaHandlePictureParameterBufferMPEG4(drv, context, buf); 131 break; 132 133 case PIPE_VIDEO_FORMAT_HEVC: 134 vlVaHandlePictureParameterBufferHEVC(drv, context, buf); 135 break; 136 137 case PIPE_VIDEO_FORMAT_JPEG: 138 vlVaHandlePictureParameterBufferMJPEG(drv, context, buf); 139 break; 140 141 case PIPE_VIDEO_FORMAT_VP9: 142 vlVaHandlePictureParameterBufferVP9(drv, context, buf); 143 break; 144 145 case PIPE_VIDEO_FORMAT_AV1: 146 vlVaHandlePictureParameterBufferAV1(drv, context, buf); 147 break; 148 149 default: 150 break; 151 } 152 153 /* Create the decoder once max_references is known. */ 154 if (!context->decoder) { 155 if (!context->target) 156 return VA_STATUS_ERROR_INVALID_CONTEXT; 157 158 if (format == PIPE_VIDEO_FORMAT_MPEG4_AVC) 159 context->templat.level = u_get_h264_level(context->templat.width, 160 context->templat.height, &context->templat.max_references); 161 162 context->decoder = drv->pipe->create_video_codec(drv->pipe, 163 &context->templat); 164 165 if (!context->decoder) 166 return VA_STATUS_ERROR_ALLOCATION_FAILED; 167 168 context->needs_begin_frame = true; 169 } 170 171 if (format == PIPE_VIDEO_FORMAT_VP9) { 172 context->decoder->width = 173 context->desc.vp9.picture_parameter.frame_width; 174 context->decoder->height = 175 context->desc.vp9.picture_parameter.frame_height; 176 } 177 178 return vaStatus; 179} 180 181static void 182handleIQMatrixBuffer(vlVaContext *context, vlVaBuffer *buf) 183{ 184 switch (u_reduce_video_profile(context->templat.profile)) { 185 case PIPE_VIDEO_FORMAT_MPEG12: 186 vlVaHandleIQMatrixBufferMPEG12(context, buf); 187 break; 188 189 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 190 vlVaHandleIQMatrixBufferH264(context, buf); 191 break; 192 193 case PIPE_VIDEO_FORMAT_MPEG4: 194 vlVaHandleIQMatrixBufferMPEG4(context, buf); 195 break; 196 197 case PIPE_VIDEO_FORMAT_HEVC: 198 vlVaHandleIQMatrixBufferHEVC(context, buf); 199 break; 200 201 case PIPE_VIDEO_FORMAT_JPEG: 202 vlVaHandleIQMatrixBufferMJPEG(context, buf); 203 break; 204 205 default: 206 break; 207 } 208} 209 210static void 211handleSliceParameterBuffer(vlVaContext *context, vlVaBuffer *buf, unsigned num) 212{ 213 switch (u_reduce_video_profile(context->templat.profile)) { 214 case PIPE_VIDEO_FORMAT_MPEG12: 215 vlVaHandleSliceParameterBufferMPEG12(context, buf); 216 break; 217 218 case PIPE_VIDEO_FORMAT_VC1: 219 vlVaHandleSliceParameterBufferVC1(context, buf); 220 break; 221 222 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 223 vlVaHandleSliceParameterBufferH264(context, buf); 224 break; 225 226 case PIPE_VIDEO_FORMAT_MPEG4: 227 vlVaHandleSliceParameterBufferMPEG4(context, buf); 228 break; 229 230 case PIPE_VIDEO_FORMAT_HEVC: 231 vlVaHandleSliceParameterBufferHEVC(context, buf); 232 break; 233 234 case PIPE_VIDEO_FORMAT_JPEG: 235 vlVaHandleSliceParameterBufferMJPEG(context, buf); 236 break; 237 238 case PIPE_VIDEO_FORMAT_VP9: 239 vlVaHandleSliceParameterBufferVP9(context, buf); 240 break; 241 242 case PIPE_VIDEO_FORMAT_AV1: 243 vlVaHandleSliceParameterBufferAV1(context, buf, num); 244 break; 245 246 default: 247 break; 248 } 249} 250 251static unsigned int 252bufHasStartcode(vlVaBuffer *buf, unsigned int code, unsigned int bits) 253{ 254 struct vl_vlc vlc = {0}; 255 int i; 256 257 /* search the first 64 bytes for a startcode */ 258 vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, &buf->size); 259 for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= bits; ++i) { 260 if (vl_vlc_peekbits(&vlc, bits) == code) 261 return 1; 262 vl_vlc_eatbits(&vlc, 8); 263 vl_vlc_fillbits(&vlc); 264 } 265 266 return 0; 267} 268 269static void 270handleVAProtectedSliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) 271{ 272 uint8_t* encrypted_data = (uint8_t*) buf->data; 273 274 unsigned int drm_key_size = buf->size; 275 276 context->desc.base.decrypt_key = CALLOC(1, drm_key_size); 277 memcpy(context->desc.base.decrypt_key, encrypted_data, drm_key_size); 278 context->desc.base.protected_playback = true; 279} 280 281static void 282handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) 283{ 284 enum pipe_video_format format = u_reduce_video_profile(context->templat.profile); 285 unsigned num_buffers = 0; 286 void * const *buffers[3]; 287 unsigned sizes[3]; 288 static const uint8_t start_code_h264[] = { 0x00, 0x00, 0x01 }; 289 static const uint8_t start_code_h265[] = { 0x00, 0x00, 0x01 }; 290 static const uint8_t start_code_vc1[] = { 0x00, 0x00, 0x01, 0x0d }; 291 static const uint8_t eoi_jpeg[] = { 0xff, 0xd9 }; 292 293 format = u_reduce_video_profile(context->templat.profile); 294 if (!context->desc.base.protected_playback) { 295 switch (format) { 296 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 297 if (bufHasStartcode(buf, 0x000001, 24)) 298 break; 299 300 buffers[num_buffers] = (void *const)&start_code_h264; 301 sizes[num_buffers++] = sizeof(start_code_h264); 302 break; 303 case PIPE_VIDEO_FORMAT_HEVC: 304 if (bufHasStartcode(buf, 0x000001, 24)) 305 break; 306 307 buffers[num_buffers] = (void *const)&start_code_h265; 308 sizes[num_buffers++] = sizeof(start_code_h265); 309 break; 310 case PIPE_VIDEO_FORMAT_VC1: 311 if (bufHasStartcode(buf, 0x0000010d, 32) || 312 bufHasStartcode(buf, 0x0000010c, 32) || 313 bufHasStartcode(buf, 0x0000010b, 32)) 314 break; 315 316 if (context->decoder->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) { 317 buffers[num_buffers] = (void *const)&start_code_vc1; 318 sizes[num_buffers++] = sizeof(start_code_vc1); 319 } 320 break; 321 case PIPE_VIDEO_FORMAT_MPEG4: 322 if (bufHasStartcode(buf, 0x000001, 24)) 323 break; 324 325 vlVaDecoderFixMPEG4Startcode(context); 326 buffers[num_buffers] = (void *)context->mpeg4.start_code; 327 sizes[num_buffers++] = context->mpeg4.start_code_size; 328 break; 329 case PIPE_VIDEO_FORMAT_JPEG: 330 vlVaGetJpegSliceHeader(context); 331 buffers[num_buffers] = (void *)context->mjpeg.slice_header; 332 sizes[num_buffers++] = context->mjpeg.slice_header_size; 333 break; 334 case PIPE_VIDEO_FORMAT_VP9: 335 if (false == context->desc.base.protected_playback) 336 vlVaDecoderVP9BitstreamHeader(context, buf); 337 break; 338 case PIPE_VIDEO_FORMAT_AV1: 339 break; 340 default: 341 break; 342 } 343 } 344 345 buffers[num_buffers] = buf->data; 346 sizes[num_buffers] = buf->size; 347 ++num_buffers; 348 349 if (format == PIPE_VIDEO_FORMAT_JPEG) { 350 buffers[num_buffers] = (void *const)&eoi_jpeg; 351 sizes[num_buffers++] = sizeof(eoi_jpeg); 352 } 353 354 if (context->needs_begin_frame) { 355 context->decoder->begin_frame(context->decoder, context->target, 356 &context->desc.base); 357 context->needs_begin_frame = false; 358 } 359 context->decoder->decode_bitstream(context->decoder, context->target, &context->desc.base, 360 num_buffers, (const void * const*)buffers, sizes); 361} 362 363static VAStatus 364handleVAEncMiscParameterTypeRateControl(vlVaContext *context, VAEncMiscParameterBuffer *misc) 365{ 366 VAStatus status = VA_STATUS_SUCCESS; 367 368 switch (u_reduce_video_profile(context->templat.profile)) { 369 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 370 status = vlVaHandleVAEncMiscParameterTypeRateControlH264(context, misc); 371 break; 372 373 case PIPE_VIDEO_FORMAT_HEVC: 374 status = vlVaHandleVAEncMiscParameterTypeRateControlHEVC(context, misc); 375 break; 376 377 default: 378 break; 379 } 380 381 return status; 382} 383 384static VAStatus 385handleVAEncMiscParameterTypeFrameRate(vlVaContext *context, VAEncMiscParameterBuffer *misc) 386{ 387 VAStatus status = VA_STATUS_SUCCESS; 388 389 switch (u_reduce_video_profile(context->templat.profile)) { 390 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 391 status = vlVaHandleVAEncMiscParameterTypeFrameRateH264(context, misc); 392 break; 393 394 case PIPE_VIDEO_FORMAT_HEVC: 395 status = vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(context, misc); 396 break; 397 398 default: 399 break; 400 } 401 402 return status; 403} 404 405static VAStatus 406handleVAEncMiscParameterTypeTemporalLayer(vlVaContext *context, VAEncMiscParameterBuffer *misc) 407{ 408 VAStatus status = VA_STATUS_SUCCESS; 409 410 switch (u_reduce_video_profile(context->templat.profile)) { 411 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 412 status = vlVaHandleVAEncMiscParameterTypeTemporalLayerH264(context, misc); 413 break; 414 415 case PIPE_VIDEO_FORMAT_HEVC: 416 break; 417 418 default: 419 break; 420 } 421 422 return status; 423} 424 425static VAStatus 426handleVAEncSequenceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 427{ 428 VAStatus status = VA_STATUS_SUCCESS; 429 430 switch (u_reduce_video_profile(context->templat.profile)) { 431 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 432 status = vlVaHandleVAEncSequenceParameterBufferTypeH264(drv, context, buf); 433 break; 434 435 case PIPE_VIDEO_FORMAT_HEVC: 436 status = vlVaHandleVAEncSequenceParameterBufferTypeHEVC(drv, context, buf); 437 break; 438 439 default: 440 break; 441 } 442 443 return status; 444} 445 446static VAStatus 447handleVAEncMiscParameterBufferType(vlVaContext *context, vlVaBuffer *buf) 448{ 449 VAStatus vaStatus = VA_STATUS_SUCCESS; 450 VAEncMiscParameterBuffer *misc; 451 misc = buf->data; 452 453 switch (misc->type) { 454 case VAEncMiscParameterTypeRateControl: 455 vaStatus = handleVAEncMiscParameterTypeRateControl(context, misc); 456 break; 457 458 case VAEncMiscParameterTypeFrameRate: 459 vaStatus = handleVAEncMiscParameterTypeFrameRate(context, misc); 460 break; 461 462 case VAEncMiscParameterTypeTemporalLayerStructure: 463 vaStatus = handleVAEncMiscParameterTypeTemporalLayer(context, misc); 464 break; 465 466 default: 467 break; 468 } 469 470 return vaStatus; 471} 472 473static VAStatus 474handleVAEncPictureParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 475{ 476 VAStatus status = VA_STATUS_SUCCESS; 477 478 switch (u_reduce_video_profile(context->templat.profile)) { 479 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 480 status = vlVaHandleVAEncPictureParameterBufferTypeH264(drv, context, buf); 481 break; 482 483 case PIPE_VIDEO_FORMAT_HEVC: 484 status = vlVaHandleVAEncPictureParameterBufferTypeHEVC(drv, context, buf); 485 break; 486 487 default: 488 break; 489 } 490 491 return status; 492} 493 494static VAStatus 495handleVAEncSliceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 496{ 497 VAStatus status = VA_STATUS_SUCCESS; 498 499 switch (u_reduce_video_profile(context->templat.profile)) { 500 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 501 status = vlVaHandleVAEncSliceParameterBufferTypeH264(drv, context, buf); 502 break; 503 504 case PIPE_VIDEO_FORMAT_HEVC: 505 status = vlVaHandleVAEncSliceParameterBufferTypeHEVC(drv, context, buf); 506 break; 507 508 default: 509 break; 510 } 511 512 return status; 513} 514 515static VAStatus 516handleVAEncPackedHeaderParameterBufferType(vlVaContext *context, vlVaBuffer *buf) 517{ 518 VAStatus status = VA_STATUS_SUCCESS; 519 520 switch (u_reduce_video_profile(context->templat.profile)) { 521 case PIPE_VIDEO_FORMAT_HEVC: 522 break; 523 524 default: 525 return VA_STATUS_ERROR_UNIMPLEMENTED; 526 } 527 528 VAEncPackedHeaderParameterBuffer *param = (VAEncPackedHeaderParameterBuffer *)buf->data; 529 if (param->type == VAEncPackedHeaderSequence) 530 context->packed_header_type = param->type; 531 else 532 status = VA_STATUS_ERROR_UNIMPLEMENTED; 533 534 return status; 535} 536 537static VAStatus 538handleVAEncPackedHeaderDataBufferType(vlVaContext *context, vlVaBuffer *buf) 539{ 540 VAStatus status = VA_STATUS_SUCCESS; 541 542 if (context->packed_header_type != VAEncPackedHeaderSequence) 543 return VA_STATUS_ERROR_UNIMPLEMENTED; 544 545 switch (u_reduce_video_profile(context->templat.profile)) { 546 case PIPE_VIDEO_FORMAT_HEVC: 547 status = vlVaHandleVAEncPackedHeaderDataBufferTypeHEVC(context, buf); 548 break; 549 550 default: 551 break; 552 } 553 554 return status; 555} 556 557VAStatus 558vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buffers, int num_buffers) 559{ 560 vlVaDriver *drv; 561 vlVaContext *context; 562 VAStatus vaStatus = VA_STATUS_SUCCESS; 563 564 unsigned i; 565 566 if (!ctx) 567 return VA_STATUS_ERROR_INVALID_CONTEXT; 568 569 drv = VL_VA_DRIVER(ctx); 570 if (!drv) 571 return VA_STATUS_ERROR_INVALID_CONTEXT; 572 573 mtx_lock(&drv->mutex); 574 context = handle_table_get(drv->htab, context_id); 575 if (!context) { 576 mtx_unlock(&drv->mutex); 577 return VA_STATUS_ERROR_INVALID_CONTEXT; 578 } 579 580 /* Always process VAProtectedSliceDataBufferType first because it changes the state */ 581 for (i = 0; i < num_buffers; ++i) { 582 vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]); 583 if (!buf) { 584 mtx_unlock(&drv->mutex); 585 return VA_STATUS_ERROR_INVALID_BUFFER; 586 } 587 588 if (buf->type == VAProtectedSliceDataBufferType) 589 handleVAProtectedSliceDataBufferType(context, buf); 590 } 591 592 for (i = 0; i < num_buffers && vaStatus == VA_STATUS_SUCCESS; ++i) { 593 vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]); 594 595 switch (buf->type) { 596 case VAPictureParameterBufferType: 597 vaStatus = handlePictureParameterBuffer(drv, context, buf); 598 break; 599 600 case VAIQMatrixBufferType: 601 handleIQMatrixBuffer(context, buf); 602 break; 603 604 case VASliceParameterBufferType: 605 handleSliceParameterBuffer(context, buf, i); 606 break; 607 608 case VASliceDataBufferType: 609 handleVASliceDataBufferType(context, buf); 610 break; 611 612 case VAProcPipelineParameterBufferType: 613 vaStatus = vlVaHandleVAProcPipelineParameterBufferType(drv, context, buf); 614 break; 615 616 case VAEncSequenceParameterBufferType: 617 vaStatus = handleVAEncSequenceParameterBufferType(drv, context, buf); 618 break; 619 620 case VAEncMiscParameterBufferType: 621 vaStatus = handleVAEncMiscParameterBufferType(context, buf); 622 break; 623 624 case VAEncPictureParameterBufferType: 625 vaStatus = handleVAEncPictureParameterBufferType(drv, context, buf); 626 break; 627 628 case VAEncSliceParameterBufferType: 629 vaStatus = handleVAEncSliceParameterBufferType(drv, context, buf); 630 break; 631 632 case VAHuffmanTableBufferType: 633 vlVaHandleHuffmanTableBufferType(context, buf); 634 break; 635 636 case VAEncPackedHeaderParameterBufferType: 637 handleVAEncPackedHeaderParameterBufferType(context, buf); 638 break; 639 case VAEncPackedHeaderDataBufferType: 640 handleVAEncPackedHeaderDataBufferType(context, buf); 641 break; 642 643 default: 644 break; 645 } 646 } 647 mtx_unlock(&drv->mutex); 648 649 return vaStatus; 650} 651 652VAStatus 653vlVaEndPicture(VADriverContextP ctx, VAContextID context_id) 654{ 655 vlVaDriver *drv; 656 vlVaContext *context; 657 vlVaBuffer *coded_buf; 658 vlVaSurface *surf; 659 void *feedback; 660 struct pipe_screen *screen; 661 bool supported; 662 bool realloc = false; 663 enum pipe_format format; 664 665 if (!ctx) 666 return VA_STATUS_ERROR_INVALID_CONTEXT; 667 668 drv = VL_VA_DRIVER(ctx); 669 if (!drv) 670 return VA_STATUS_ERROR_INVALID_CONTEXT; 671 672 mtx_lock(&drv->mutex); 673 context = handle_table_get(drv->htab, context_id); 674 mtx_unlock(&drv->mutex); 675 if (!context) 676 return VA_STATUS_ERROR_INVALID_CONTEXT; 677 678 if (!context->decoder) { 679 if (context->templat.profile != PIPE_VIDEO_PROFILE_UNKNOWN) 680 return VA_STATUS_ERROR_INVALID_CONTEXT; 681 682 /* VPP */ 683 return VA_STATUS_SUCCESS; 684 } 685 686 mtx_lock(&drv->mutex); 687 surf = handle_table_get(drv->htab, context->target_id); 688 context->mpeg4.frame_num++; 689 690 screen = context->decoder->context->screen; 691 supported = screen->get_video_param(screen, context->decoder->profile, 692 context->decoder->entrypoint, 693 surf->buffer->interlaced ? 694 PIPE_VIDEO_CAP_SUPPORTS_INTERLACED : 695 PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE); 696 697 if (!supported) { 698 surf->templat.interlaced = screen->get_video_param(screen, 699 context->decoder->profile, 700 context->decoder->entrypoint, 701 PIPE_VIDEO_CAP_PREFERS_INTERLACED); 702 realloc = true; 703 } 704 705 format = screen->get_video_param(screen, context->decoder->profile, 706 context->decoder->entrypoint, 707 PIPE_VIDEO_CAP_PREFERED_FORMAT); 708 709 if (surf->buffer->buffer_format != format && 710 surf->buffer->buffer_format == PIPE_FORMAT_NV12) { 711 /* check originally as NV12 only */ 712 surf->templat.buffer_format = format; 713 realloc = true; 714 } 715 716 if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_JPEG && 717 surf->buffer->buffer_format == PIPE_FORMAT_NV12) { 718 if (context->mjpeg.sampling_factor == 0x211111 || 719 context->mjpeg.sampling_factor == 0x221212) { 720 surf->templat.buffer_format = PIPE_FORMAT_YUYV; 721 realloc = true; 722 } else if (context->mjpeg.sampling_factor != 0x221111) { 723 /* Not NV12 either */ 724 mtx_unlock(&drv->mutex); 725 return VA_STATUS_ERROR_INVALID_SURFACE; 726 } 727 } 728 729 if ((bool)(surf->templat.bind & PIPE_BIND_PROTECTED) != context->desc.base.protected_playback) { 730 if (context->desc.base.protected_playback) { 731 surf->templat.bind |= PIPE_BIND_PROTECTED; 732 } 733 else 734 surf->templat.bind &= ~PIPE_BIND_PROTECTED; 735 realloc = true; 736 } 737 738 if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_AV1 && 739 surf->buffer->buffer_format == PIPE_FORMAT_NV12) { 740 if (context->desc.av1.picture_parameter.bit_depth_idx == 1) { 741 surf->templat.buffer_format = PIPE_FORMAT_P010; 742 realloc = true; 743 } 744 } 745 746 if (realloc) { 747 struct pipe_video_buffer *old_buf = surf->buffer; 748 749 if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS) { 750 mtx_unlock(&drv->mutex); 751 return VA_STATUS_ERROR_ALLOCATION_FAILED; 752 } 753 754 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 755 if (old_buf->interlaced) { 756 struct u_rect src_rect, dst_rect; 757 758 dst_rect.x0 = src_rect.x0 = 0; 759 dst_rect.y0 = src_rect.y0 = 0; 760 dst_rect.x1 = src_rect.x1 = surf->templat.width; 761 dst_rect.y1 = src_rect.y1 = surf->templat.height; 762 vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor, 763 old_buf, surf->buffer, 764 &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE); 765 } else { 766 /* Can't convert from progressive to interlaced yet */ 767 mtx_unlock(&drv->mutex); 768 return VA_STATUS_ERROR_INVALID_SURFACE; 769 } 770 } 771 772 old_buf->destroy(old_buf); 773 context->target = surf->buffer; 774 } 775 776 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 777 coded_buf = context->coded_buf; 778 if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { 779 getEncParamPresetH264(context); 780 context->desc.h264enc.frame_num_cnt++; 781 } else if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC) 782 getEncParamPresetH265(context); 783 context->decoder->begin_frame(context->decoder, context->target, &context->desc.base); 784 context->decoder->encode_bitstream(context->decoder, context->target, 785 coded_buf->derived_surface.resource, &feedback); 786 surf->feedback = feedback; 787 surf->coded_buf = coded_buf; 788 } 789 790 context->decoder->end_frame(context->decoder, context->target, &context->desc.base); 791 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE && 792 u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { 793 int idr_period = context->desc.h264enc.gop_size / context->gop_coeff; 794 int p_remain_in_idr = idr_period - context->desc.h264enc.frame_num; 795 surf->frame_num_cnt = context->desc.h264enc.frame_num_cnt; 796 surf->force_flushed = false; 797 if (context->first_single_submitted) { 798 context->decoder->flush(context->decoder); 799 context->first_single_submitted = false; 800 surf->force_flushed = true; 801 } 802 if (p_remain_in_idr == 1) { 803 if ((context->desc.h264enc.frame_num_cnt % 2) != 0) { 804 context->decoder->flush(context->decoder); 805 context->first_single_submitted = true; 806 } 807 else 808 context->first_single_submitted = false; 809 surf->force_flushed = true; 810 } 811 } else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE && 812 u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC) 813 context->desc.h265enc.frame_num++; 814 mtx_unlock(&drv->mutex); 815 return VA_STATUS_SUCCESS; 816} 817