1b8e80941Smrg/************************************************************************** 2b8e80941Smrg * 3b8e80941Smrg * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. 4b8e80941Smrg * Copyright 2014 Advanced Micro Devices, Inc. 5b8e80941Smrg * All Rights Reserved. 6b8e80941Smrg * 7b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8b8e80941Smrg * copy of this software and associated documentation files (the 9b8e80941Smrg * "Software"), to deal in the Software without restriction, including 10b8e80941Smrg * without limitation the rights to use, copy, modify, merge, publish, 11b8e80941Smrg * distribute, sub license, and/or sell copies of the Software, and to 12b8e80941Smrg * permit persons to whom the Software is furnished to do so, subject to 13b8e80941Smrg * the following conditions: 14b8e80941Smrg * 15b8e80941Smrg * The above copyright notice and this permission notice (including the 16b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions 17b8e80941Smrg * of the Software. 18b8e80941Smrg * 19b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21b8e80941Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22b8e80941Smrg * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 23b8e80941Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24b8e80941Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25b8e80941Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26b8e80941Smrg * 27b8e80941Smrg **************************************************************************/ 28b8e80941Smrg 29b8e80941Smrg#include "pipe/p_video_codec.h" 30b8e80941Smrg 31b8e80941Smrg#include "util/u_handle_table.h" 32b8e80941Smrg#include "util/u_video.h" 33b8e80941Smrg 34b8e80941Smrg#include "vl/vl_vlc.h" 35b8e80941Smrg#include "vl/vl_winsys.h" 36b8e80941Smrg 37b8e80941Smrg#include "va_private.h" 38b8e80941Smrg 39b8e80941SmrgVAStatus 40b8e80941SmrgvlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID render_target) 41b8e80941Smrg{ 42b8e80941Smrg vlVaDriver *drv; 43b8e80941Smrg vlVaContext *context; 44b8e80941Smrg vlVaSurface *surf; 45b8e80941Smrg 46b8e80941Smrg if (!ctx) 47b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 48b8e80941Smrg 49b8e80941Smrg drv = VL_VA_DRIVER(ctx); 50b8e80941Smrg if (!drv) 51b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 52b8e80941Smrg 53b8e80941Smrg mtx_lock(&drv->mutex); 54b8e80941Smrg context = handle_table_get(drv->htab, context_id); 55b8e80941Smrg if (!context) { 56b8e80941Smrg mtx_unlock(&drv->mutex); 57b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 58b8e80941Smrg } 59b8e80941Smrg 60b8e80941Smrg if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG12) { 61b8e80941Smrg context->desc.mpeg12.intra_matrix = NULL; 62b8e80941Smrg context->desc.mpeg12.non_intra_matrix = NULL; 63b8e80941Smrg } 64b8e80941Smrg 65b8e80941Smrg surf = handle_table_get(drv->htab, render_target); 66b8e80941Smrg mtx_unlock(&drv->mutex); 67b8e80941Smrg if (!surf || !surf->buffer) 68b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 69b8e80941Smrg 70b8e80941Smrg context->target_id = render_target; 71b8e80941Smrg surf->ctx = context_id; 72b8e80941Smrg context->target = surf->buffer; 73b8e80941Smrg context->mjpeg.sampling_factor = 0; 74b8e80941Smrg 75b8e80941Smrg if (!context->decoder) { 76b8e80941Smrg 77b8e80941Smrg /* VPP */ 78b8e80941Smrg if (context->templat.profile == PIPE_VIDEO_PROFILE_UNKNOWN && 79b8e80941Smrg context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM && 80b8e80941Smrg context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM && 81b8e80941Smrg context->target->buffer_format != PIPE_FORMAT_B8G8R8X8_UNORM && 82b8e80941Smrg context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM && 83b8e80941Smrg context->target->buffer_format != PIPE_FORMAT_NV12 && 84b8e80941Smrg context->target->buffer_format != PIPE_FORMAT_P016) 85b8e80941Smrg return VA_STATUS_ERROR_UNIMPLEMENTED; 86b8e80941Smrg 87b8e80941Smrg return VA_STATUS_SUCCESS; 88b8e80941Smrg } 89b8e80941Smrg 90b8e80941Smrg if (context->decoder->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) 91b8e80941Smrg context->needs_begin_frame = true; 92b8e80941Smrg 93b8e80941Smrg return VA_STATUS_SUCCESS; 94b8e80941Smrg} 95b8e80941Smrg 96b8e80941Smrgvoid 97b8e80941SmrgvlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, 98b8e80941Smrg struct pipe_video_buffer **ref_frame) 99b8e80941Smrg{ 100b8e80941Smrg vlVaSurface *surf = handle_table_get(drv->htab, surface_id); 101b8e80941Smrg if (surf) 102b8e80941Smrg *ref_frame = surf->buffer; 103b8e80941Smrg else 104b8e80941Smrg *ref_frame = NULL; 105b8e80941Smrg} 106b8e80941Smrg 107b8e80941Smrgstatic VAStatus 108b8e80941SmrghandlePictureParameterBuffer(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 109b8e80941Smrg{ 110b8e80941Smrg VAStatus vaStatus = VA_STATUS_SUCCESS; 111b8e80941Smrg 112b8e80941Smrg switch (u_reduce_video_profile(context->templat.profile)) { 113b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG12: 114b8e80941Smrg vlVaHandlePictureParameterBufferMPEG12(drv, context, buf); 115b8e80941Smrg break; 116b8e80941Smrg 117b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4_AVC: 118b8e80941Smrg vlVaHandlePictureParameterBufferH264(drv, context, buf); 119b8e80941Smrg break; 120b8e80941Smrg 121b8e80941Smrg case PIPE_VIDEO_FORMAT_VC1: 122b8e80941Smrg vlVaHandlePictureParameterBufferVC1(drv, context, buf); 123b8e80941Smrg break; 124b8e80941Smrg 125b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4: 126b8e80941Smrg vlVaHandlePictureParameterBufferMPEG4(drv, context, buf); 127b8e80941Smrg break; 128b8e80941Smrg 129b8e80941Smrg case PIPE_VIDEO_FORMAT_HEVC: 130b8e80941Smrg vlVaHandlePictureParameterBufferHEVC(drv, context, buf); 131b8e80941Smrg break; 132b8e80941Smrg 133b8e80941Smrg case PIPE_VIDEO_FORMAT_JPEG: 134b8e80941Smrg vlVaHandlePictureParameterBufferMJPEG(drv, context, buf); 135b8e80941Smrg break; 136b8e80941Smrg 137b8e80941Smrg case PIPE_VIDEO_FORMAT_VP9: 138b8e80941Smrg vlVaHandlePictureParameterBufferVP9(drv, context, buf); 139b8e80941Smrg break; 140b8e80941Smrg 141b8e80941Smrg default: 142b8e80941Smrg break; 143b8e80941Smrg } 144b8e80941Smrg 145b8e80941Smrg /* Create the decoder once max_references is known. */ 146b8e80941Smrg if (!context->decoder) { 147b8e80941Smrg enum pipe_video_format format = 148b8e80941Smrg u_reduce_video_profile(context->templat.profile); 149b8e80941Smrg 150b8e80941Smrg if (!context->target) 151b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 152b8e80941Smrg 153b8e80941Smrg if (context->templat.max_references == 0 && 154b8e80941Smrg format != PIPE_VIDEO_FORMAT_JPEG) 155b8e80941Smrg return VA_STATUS_ERROR_INVALID_BUFFER; 156b8e80941Smrg 157b8e80941Smrg if (format == PIPE_VIDEO_FORMAT_MPEG4_AVC) 158b8e80941Smrg context->templat.level = u_get_h264_level(context->templat.width, 159b8e80941Smrg context->templat.height, &context->templat.max_references); 160b8e80941Smrg 161b8e80941Smrg context->decoder = drv->pipe->create_video_codec(drv->pipe, 162b8e80941Smrg &context->templat); 163b8e80941Smrg 164b8e80941Smrg if (!context->decoder) 165b8e80941Smrg return VA_STATUS_ERROR_ALLOCATION_FAILED; 166b8e80941Smrg 167b8e80941Smrg context->needs_begin_frame = true; 168b8e80941Smrg } 169b8e80941Smrg 170b8e80941Smrg return vaStatus; 171b8e80941Smrg} 172b8e80941Smrg 173b8e80941Smrgstatic void 174b8e80941SmrghandleIQMatrixBuffer(vlVaContext *context, vlVaBuffer *buf) 175b8e80941Smrg{ 176b8e80941Smrg switch (u_reduce_video_profile(context->templat.profile)) { 177b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG12: 178b8e80941Smrg vlVaHandleIQMatrixBufferMPEG12(context, buf); 179b8e80941Smrg break; 180b8e80941Smrg 181b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4_AVC: 182b8e80941Smrg vlVaHandleIQMatrixBufferH264(context, buf); 183b8e80941Smrg break; 184b8e80941Smrg 185b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4: 186b8e80941Smrg vlVaHandleIQMatrixBufferMPEG4(context, buf); 187b8e80941Smrg break; 188b8e80941Smrg 189b8e80941Smrg case PIPE_VIDEO_FORMAT_HEVC: 190b8e80941Smrg vlVaHandleIQMatrixBufferHEVC(context, buf); 191b8e80941Smrg break; 192b8e80941Smrg 193b8e80941Smrg case PIPE_VIDEO_FORMAT_JPEG: 194b8e80941Smrg vlVaHandleIQMatrixBufferMJPEG(context, buf); 195b8e80941Smrg break; 196b8e80941Smrg 197b8e80941Smrg default: 198b8e80941Smrg break; 199b8e80941Smrg } 200b8e80941Smrg} 201b8e80941Smrg 202b8e80941Smrgstatic void 203b8e80941SmrghandleSliceParameterBuffer(vlVaContext *context, vlVaBuffer *buf) 204b8e80941Smrg{ 205b8e80941Smrg switch (u_reduce_video_profile(context->templat.profile)) { 206b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG12: 207b8e80941Smrg vlVaHandleSliceParameterBufferMPEG12(context, buf); 208b8e80941Smrg break; 209b8e80941Smrg 210b8e80941Smrg case PIPE_VIDEO_FORMAT_VC1: 211b8e80941Smrg vlVaHandleSliceParameterBufferVC1(context, buf); 212b8e80941Smrg break; 213b8e80941Smrg 214b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4_AVC: 215b8e80941Smrg vlVaHandleSliceParameterBufferH264(context, buf); 216b8e80941Smrg break; 217b8e80941Smrg 218b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4: 219b8e80941Smrg vlVaHandleSliceParameterBufferMPEG4(context, buf); 220b8e80941Smrg break; 221b8e80941Smrg 222b8e80941Smrg case PIPE_VIDEO_FORMAT_HEVC: 223b8e80941Smrg vlVaHandleSliceParameterBufferHEVC(context, buf); 224b8e80941Smrg break; 225b8e80941Smrg 226b8e80941Smrg case PIPE_VIDEO_FORMAT_JPEG: 227b8e80941Smrg vlVaHandleSliceParameterBufferMJPEG(context, buf); 228b8e80941Smrg break; 229b8e80941Smrg 230b8e80941Smrg case PIPE_VIDEO_FORMAT_VP9: 231b8e80941Smrg vlVaHandleSliceParameterBufferVP9(context, buf); 232b8e80941Smrg break; 233b8e80941Smrg 234b8e80941Smrg default: 235b8e80941Smrg break; 236b8e80941Smrg } 237b8e80941Smrg} 238b8e80941Smrg 239b8e80941Smrgstatic unsigned int 240b8e80941SmrgbufHasStartcode(vlVaBuffer *buf, unsigned int code, unsigned int bits) 241b8e80941Smrg{ 242b8e80941Smrg struct vl_vlc vlc = {0}; 243b8e80941Smrg int i; 244b8e80941Smrg 245b8e80941Smrg /* search the first 64 bytes for a startcode */ 246b8e80941Smrg vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, &buf->size); 247b8e80941Smrg for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= bits; ++i) { 248b8e80941Smrg if (vl_vlc_peekbits(&vlc, bits) == code) 249b8e80941Smrg return 1; 250b8e80941Smrg vl_vlc_eatbits(&vlc, 8); 251b8e80941Smrg vl_vlc_fillbits(&vlc); 252b8e80941Smrg } 253b8e80941Smrg 254b8e80941Smrg return 0; 255b8e80941Smrg} 256b8e80941Smrg 257b8e80941Smrgstatic void 258b8e80941SmrghandleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) 259b8e80941Smrg{ 260b8e80941Smrg enum pipe_video_format format; 261b8e80941Smrg unsigned num_buffers = 0; 262b8e80941Smrg void * const *buffers[3]; 263b8e80941Smrg unsigned sizes[3]; 264b8e80941Smrg static const uint8_t start_code_h264[] = { 0x00, 0x00, 0x01 }; 265b8e80941Smrg static const uint8_t start_code_h265[] = { 0x00, 0x00, 0x01 }; 266b8e80941Smrg static const uint8_t start_code_vc1[] = { 0x00, 0x00, 0x01, 0x0d }; 267b8e80941Smrg static const uint8_t eoi_jpeg[] = { 0xff, 0xd9 }; 268b8e80941Smrg 269b8e80941Smrg format = u_reduce_video_profile(context->templat.profile); 270b8e80941Smrg switch (format) { 271b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4_AVC: 272b8e80941Smrg if (bufHasStartcode(buf, 0x000001, 24)) 273b8e80941Smrg break; 274b8e80941Smrg 275b8e80941Smrg buffers[num_buffers] = (void *const)&start_code_h264; 276b8e80941Smrg sizes[num_buffers++] = sizeof(start_code_h264); 277b8e80941Smrg break; 278b8e80941Smrg case PIPE_VIDEO_FORMAT_HEVC: 279b8e80941Smrg if (bufHasStartcode(buf, 0x000001, 24)) 280b8e80941Smrg break; 281b8e80941Smrg 282b8e80941Smrg buffers[num_buffers] = (void *const)&start_code_h265; 283b8e80941Smrg sizes[num_buffers++] = sizeof(start_code_h265); 284b8e80941Smrg break; 285b8e80941Smrg case PIPE_VIDEO_FORMAT_VC1: 286b8e80941Smrg if (bufHasStartcode(buf, 0x0000010d, 32) || 287b8e80941Smrg bufHasStartcode(buf, 0x0000010c, 32) || 288b8e80941Smrg bufHasStartcode(buf, 0x0000010b, 32)) 289b8e80941Smrg break; 290b8e80941Smrg 291b8e80941Smrg if (context->decoder->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) { 292b8e80941Smrg buffers[num_buffers] = (void *const)&start_code_vc1; 293b8e80941Smrg sizes[num_buffers++] = sizeof(start_code_vc1); 294b8e80941Smrg } 295b8e80941Smrg break; 296b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4: 297b8e80941Smrg if (bufHasStartcode(buf, 0x000001, 24)) 298b8e80941Smrg break; 299b8e80941Smrg 300b8e80941Smrg vlVaDecoderFixMPEG4Startcode(context); 301b8e80941Smrg buffers[num_buffers] = (void *)context->mpeg4.start_code; 302b8e80941Smrg sizes[num_buffers++] = context->mpeg4.start_code_size; 303b8e80941Smrg break; 304b8e80941Smrg case PIPE_VIDEO_FORMAT_JPEG: 305b8e80941Smrg vlVaGetJpegSliceHeader(context); 306b8e80941Smrg buffers[num_buffers] = (void *)context->mjpeg.slice_header; 307b8e80941Smrg sizes[num_buffers++] = context->mjpeg.slice_header_size; 308b8e80941Smrg break; 309b8e80941Smrg case PIPE_VIDEO_FORMAT_VP9: 310b8e80941Smrg vlVaDecoderVP9BitstreamHeader(context, buf); 311b8e80941Smrg break; 312b8e80941Smrg default: 313b8e80941Smrg break; 314b8e80941Smrg } 315b8e80941Smrg 316b8e80941Smrg buffers[num_buffers] = buf->data; 317b8e80941Smrg sizes[num_buffers] = buf->size; 318b8e80941Smrg ++num_buffers; 319b8e80941Smrg 320b8e80941Smrg if (format == PIPE_VIDEO_FORMAT_JPEG) { 321b8e80941Smrg buffers[num_buffers] = (void *const)&eoi_jpeg; 322b8e80941Smrg sizes[num_buffers++] = sizeof(eoi_jpeg); 323b8e80941Smrg } 324b8e80941Smrg 325b8e80941Smrg if (context->needs_begin_frame) { 326b8e80941Smrg context->decoder->begin_frame(context->decoder, context->target, 327b8e80941Smrg &context->desc.base); 328b8e80941Smrg context->needs_begin_frame = false; 329b8e80941Smrg } 330b8e80941Smrg context->decoder->decode_bitstream(context->decoder, context->target, &context->desc.base, 331b8e80941Smrg num_buffers, (const void * const*)buffers, sizes); 332b8e80941Smrg} 333b8e80941Smrg 334b8e80941Smrgstatic VAStatus 335b8e80941SmrghandleVAEncMiscParameterTypeRateControl(vlVaContext *context, VAEncMiscParameterBuffer *misc) 336b8e80941Smrg{ 337b8e80941Smrg VAStatus status = VA_STATUS_SUCCESS; 338b8e80941Smrg 339b8e80941Smrg switch (u_reduce_video_profile(context->templat.profile)) { 340b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4_AVC: 341b8e80941Smrg status = vlVaHandleVAEncMiscParameterTypeRateControlH264(context, misc); 342b8e80941Smrg break; 343b8e80941Smrg 344b8e80941Smrg case PIPE_VIDEO_FORMAT_HEVC: 345b8e80941Smrg status = vlVaHandleVAEncMiscParameterTypeRateControlHEVC(context, misc); 346b8e80941Smrg break; 347b8e80941Smrg 348b8e80941Smrg default: 349b8e80941Smrg break; 350b8e80941Smrg } 351b8e80941Smrg 352b8e80941Smrg return status; 353b8e80941Smrg} 354b8e80941Smrg 355b8e80941Smrgstatic VAStatus 356b8e80941SmrghandleVAEncMiscParameterTypeFrameRate(vlVaContext *context, VAEncMiscParameterBuffer *misc) 357b8e80941Smrg{ 358b8e80941Smrg VAStatus status = VA_STATUS_SUCCESS; 359b8e80941Smrg 360b8e80941Smrg switch (u_reduce_video_profile(context->templat.profile)) { 361b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4_AVC: 362b8e80941Smrg status = vlVaHandleVAEncMiscParameterTypeFrameRateH264(context, misc); 363b8e80941Smrg break; 364b8e80941Smrg 365b8e80941Smrg case PIPE_VIDEO_FORMAT_HEVC: 366b8e80941Smrg status = vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(context, misc); 367b8e80941Smrg break; 368b8e80941Smrg 369b8e80941Smrg default: 370b8e80941Smrg break; 371b8e80941Smrg } 372b8e80941Smrg 373b8e80941Smrg return status; 374b8e80941Smrg} 375b8e80941Smrg 376b8e80941Smrgstatic VAStatus 377b8e80941SmrghandleVAEncSequenceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 378b8e80941Smrg{ 379b8e80941Smrg VAStatus status = VA_STATUS_SUCCESS; 380b8e80941Smrg 381b8e80941Smrg switch (u_reduce_video_profile(context->templat.profile)) { 382b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4_AVC: 383b8e80941Smrg status = vlVaHandleVAEncSequenceParameterBufferTypeH264(drv, context, buf); 384b8e80941Smrg break; 385b8e80941Smrg 386b8e80941Smrg case PIPE_VIDEO_FORMAT_HEVC: 387b8e80941Smrg status = vlVaHandleVAEncSequenceParameterBufferTypeHEVC(drv, context, buf); 388b8e80941Smrg break; 389b8e80941Smrg 390b8e80941Smrg default: 391b8e80941Smrg break; 392b8e80941Smrg } 393b8e80941Smrg 394b8e80941Smrg return status; 395b8e80941Smrg} 396b8e80941Smrg 397b8e80941Smrgstatic VAStatus 398b8e80941SmrghandleVAEncMiscParameterBufferType(vlVaContext *context, vlVaBuffer *buf) 399b8e80941Smrg{ 400b8e80941Smrg VAStatus vaStatus = VA_STATUS_SUCCESS; 401b8e80941Smrg VAEncMiscParameterBuffer *misc; 402b8e80941Smrg misc = buf->data; 403b8e80941Smrg 404b8e80941Smrg switch (misc->type) { 405b8e80941Smrg case VAEncMiscParameterTypeRateControl: 406b8e80941Smrg vaStatus = handleVAEncMiscParameterTypeRateControl(context, misc); 407b8e80941Smrg break; 408b8e80941Smrg 409b8e80941Smrg case VAEncMiscParameterTypeFrameRate: 410b8e80941Smrg vaStatus = handleVAEncMiscParameterTypeFrameRate(context, misc); 411b8e80941Smrg break; 412b8e80941Smrg 413b8e80941Smrg default: 414b8e80941Smrg break; 415b8e80941Smrg } 416b8e80941Smrg 417b8e80941Smrg return vaStatus; 418b8e80941Smrg} 419b8e80941Smrg 420b8e80941Smrgstatic VAStatus 421b8e80941SmrghandleVAEncPictureParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 422b8e80941Smrg{ 423b8e80941Smrg VAStatus status = VA_STATUS_SUCCESS; 424b8e80941Smrg 425b8e80941Smrg switch (u_reduce_video_profile(context->templat.profile)) { 426b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4_AVC: 427b8e80941Smrg status = vlVaHandleVAEncPictureParameterBufferTypeH264(drv, context, buf); 428b8e80941Smrg break; 429b8e80941Smrg 430b8e80941Smrg case PIPE_VIDEO_FORMAT_HEVC: 431b8e80941Smrg status = vlVaHandleVAEncPictureParameterBufferTypeHEVC(drv, context, buf); 432b8e80941Smrg break; 433b8e80941Smrg 434b8e80941Smrg default: 435b8e80941Smrg break; 436b8e80941Smrg } 437b8e80941Smrg 438b8e80941Smrg return status; 439b8e80941Smrg} 440b8e80941Smrg 441b8e80941Smrgstatic VAStatus 442b8e80941SmrghandleVAEncSliceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) 443b8e80941Smrg{ 444b8e80941Smrg VAStatus status = VA_STATUS_SUCCESS; 445b8e80941Smrg 446b8e80941Smrg switch (u_reduce_video_profile(context->templat.profile)) { 447b8e80941Smrg case PIPE_VIDEO_FORMAT_MPEG4_AVC: 448b8e80941Smrg status = vlVaHandleVAEncSliceParameterBufferTypeH264(drv, context, buf); 449b8e80941Smrg break; 450b8e80941Smrg 451b8e80941Smrg case PIPE_VIDEO_FORMAT_HEVC: 452b8e80941Smrg status = vlVaHandleVAEncSliceParameterBufferTypeHEVC(drv, context, buf); 453b8e80941Smrg break; 454b8e80941Smrg 455b8e80941Smrg default: 456b8e80941Smrg break; 457b8e80941Smrg } 458b8e80941Smrg 459b8e80941Smrg return status; 460b8e80941Smrg} 461b8e80941Smrg 462b8e80941SmrgVAStatus 463b8e80941SmrgvlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buffers, int num_buffers) 464b8e80941Smrg{ 465b8e80941Smrg vlVaDriver *drv; 466b8e80941Smrg vlVaContext *context; 467b8e80941Smrg VAStatus vaStatus = VA_STATUS_SUCCESS; 468b8e80941Smrg 469b8e80941Smrg unsigned i; 470b8e80941Smrg 471b8e80941Smrg if (!ctx) 472b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 473b8e80941Smrg 474b8e80941Smrg drv = VL_VA_DRIVER(ctx); 475b8e80941Smrg if (!drv) 476b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 477b8e80941Smrg 478b8e80941Smrg mtx_lock(&drv->mutex); 479b8e80941Smrg context = handle_table_get(drv->htab, context_id); 480b8e80941Smrg if (!context) { 481b8e80941Smrg mtx_unlock(&drv->mutex); 482b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 483b8e80941Smrg } 484b8e80941Smrg 485b8e80941Smrg for (i = 0; i < num_buffers; ++i) { 486b8e80941Smrg vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]); 487b8e80941Smrg if (!buf) { 488b8e80941Smrg mtx_unlock(&drv->mutex); 489b8e80941Smrg return VA_STATUS_ERROR_INVALID_BUFFER; 490b8e80941Smrg } 491b8e80941Smrg 492b8e80941Smrg switch (buf->type) { 493b8e80941Smrg case VAPictureParameterBufferType: 494b8e80941Smrg vaStatus = handlePictureParameterBuffer(drv, context, buf); 495b8e80941Smrg break; 496b8e80941Smrg 497b8e80941Smrg case VAIQMatrixBufferType: 498b8e80941Smrg handleIQMatrixBuffer(context, buf); 499b8e80941Smrg break; 500b8e80941Smrg 501b8e80941Smrg case VASliceParameterBufferType: 502b8e80941Smrg handleSliceParameterBuffer(context, buf); 503b8e80941Smrg break; 504b8e80941Smrg 505b8e80941Smrg case VASliceDataBufferType: 506b8e80941Smrg handleVASliceDataBufferType(context, buf); 507b8e80941Smrg break; 508b8e80941Smrg case VAProcPipelineParameterBufferType: 509b8e80941Smrg vaStatus = vlVaHandleVAProcPipelineParameterBufferType(drv, context, buf); 510b8e80941Smrg break; 511b8e80941Smrg 512b8e80941Smrg case VAEncSequenceParameterBufferType: 513b8e80941Smrg vaStatus = handleVAEncSequenceParameterBufferType(drv, context, buf); 514b8e80941Smrg break; 515b8e80941Smrg 516b8e80941Smrg case VAEncMiscParameterBufferType: 517b8e80941Smrg vaStatus = handleVAEncMiscParameterBufferType(context, buf); 518b8e80941Smrg break; 519b8e80941Smrg 520b8e80941Smrg case VAEncPictureParameterBufferType: 521b8e80941Smrg vaStatus = handleVAEncPictureParameterBufferType(drv, context, buf); 522b8e80941Smrg break; 523b8e80941Smrg 524b8e80941Smrg case VAEncSliceParameterBufferType: 525b8e80941Smrg vaStatus = handleVAEncSliceParameterBufferType(drv, context, buf); 526b8e80941Smrg break; 527b8e80941Smrg 528b8e80941Smrg case VAHuffmanTableBufferType: 529b8e80941Smrg vlVaHandleHuffmanTableBufferType(context, buf); 530b8e80941Smrg break; 531b8e80941Smrg 532b8e80941Smrg default: 533b8e80941Smrg break; 534b8e80941Smrg } 535b8e80941Smrg } 536b8e80941Smrg mtx_unlock(&drv->mutex); 537b8e80941Smrg 538b8e80941Smrg return vaStatus; 539b8e80941Smrg} 540b8e80941Smrg 541b8e80941SmrgVAStatus 542b8e80941SmrgvlVaEndPicture(VADriverContextP ctx, VAContextID context_id) 543b8e80941Smrg{ 544b8e80941Smrg vlVaDriver *drv; 545b8e80941Smrg vlVaContext *context; 546b8e80941Smrg vlVaBuffer *coded_buf; 547b8e80941Smrg vlVaSurface *surf; 548b8e80941Smrg void *feedback; 549b8e80941Smrg struct pipe_screen *screen; 550b8e80941Smrg bool supported; 551b8e80941Smrg bool realloc = false; 552b8e80941Smrg enum pipe_format format; 553b8e80941Smrg 554b8e80941Smrg if (!ctx) 555b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 556b8e80941Smrg 557b8e80941Smrg drv = VL_VA_DRIVER(ctx); 558b8e80941Smrg if (!drv) 559b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 560b8e80941Smrg 561b8e80941Smrg mtx_lock(&drv->mutex); 562b8e80941Smrg context = handle_table_get(drv->htab, context_id); 563b8e80941Smrg mtx_unlock(&drv->mutex); 564b8e80941Smrg if (!context) 565b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 566b8e80941Smrg 567b8e80941Smrg if (!context->decoder) { 568b8e80941Smrg if (context->templat.profile != PIPE_VIDEO_PROFILE_UNKNOWN) 569b8e80941Smrg return VA_STATUS_ERROR_INVALID_CONTEXT; 570b8e80941Smrg 571b8e80941Smrg /* VPP */ 572b8e80941Smrg return VA_STATUS_SUCCESS; 573b8e80941Smrg } 574b8e80941Smrg 575b8e80941Smrg mtx_lock(&drv->mutex); 576b8e80941Smrg surf = handle_table_get(drv->htab, context->target_id); 577b8e80941Smrg context->mpeg4.frame_num++; 578b8e80941Smrg 579b8e80941Smrg screen = context->decoder->context->screen; 580b8e80941Smrg supported = screen->get_video_param(screen, context->decoder->profile, 581b8e80941Smrg context->decoder->entrypoint, 582b8e80941Smrg surf->buffer->interlaced ? 583b8e80941Smrg PIPE_VIDEO_CAP_SUPPORTS_INTERLACED : 584b8e80941Smrg PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE); 585b8e80941Smrg 586b8e80941Smrg if (!supported) { 587b8e80941Smrg surf->templat.interlaced = screen->get_video_param(screen, 588b8e80941Smrg context->decoder->profile, 589b8e80941Smrg context->decoder->entrypoint, 590b8e80941Smrg PIPE_VIDEO_CAP_PREFERS_INTERLACED); 591b8e80941Smrg realloc = true; 592b8e80941Smrg } 593b8e80941Smrg 594b8e80941Smrg format = screen->get_video_param(screen, context->decoder->profile, 595b8e80941Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 596b8e80941Smrg PIPE_VIDEO_CAP_PREFERED_FORMAT); 597b8e80941Smrg 598b8e80941Smrg if (surf->buffer->buffer_format != format && 599b8e80941Smrg surf->buffer->buffer_format == PIPE_FORMAT_NV12) { 600b8e80941Smrg /* check originally as NV12 only */ 601b8e80941Smrg surf->templat.buffer_format = format; 602b8e80941Smrg realloc = true; 603b8e80941Smrg } 604b8e80941Smrg 605b8e80941Smrg if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_JPEG && 606b8e80941Smrg surf->buffer->buffer_format == PIPE_FORMAT_NV12) { 607b8e80941Smrg if (context->mjpeg.sampling_factor == 0x211111 || 608b8e80941Smrg context->mjpeg.sampling_factor == 0x221212) { 609b8e80941Smrg surf->templat.buffer_format = PIPE_FORMAT_YUYV; 610b8e80941Smrg realloc = true; 611b8e80941Smrg } else if (context->mjpeg.sampling_factor != 0x221111) { 612b8e80941Smrg /* Not NV12 either */ 613b8e80941Smrg mtx_unlock(&drv->mutex); 614b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 615b8e80941Smrg } 616b8e80941Smrg } 617b8e80941Smrg 618b8e80941Smrg if (realloc) { 619b8e80941Smrg struct pipe_video_buffer *old_buf = surf->buffer; 620b8e80941Smrg 621b8e80941Smrg if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) { 622b8e80941Smrg mtx_unlock(&drv->mutex); 623b8e80941Smrg return VA_STATUS_ERROR_ALLOCATION_FAILED; 624b8e80941Smrg } 625b8e80941Smrg 626b8e80941Smrg if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 627b8e80941Smrg if (old_buf->interlaced) { 628b8e80941Smrg struct u_rect src_rect, dst_rect; 629b8e80941Smrg 630b8e80941Smrg dst_rect.x0 = src_rect.x0 = 0; 631b8e80941Smrg dst_rect.y0 = src_rect.y0 = 0; 632b8e80941Smrg dst_rect.x1 = src_rect.x1 = surf->templat.width; 633b8e80941Smrg dst_rect.y1 = src_rect.y1 = surf->templat.height; 634b8e80941Smrg vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor, 635b8e80941Smrg old_buf, surf->buffer, 636b8e80941Smrg &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE); 637b8e80941Smrg } else { 638b8e80941Smrg /* Can't convert from progressive to interlaced yet */ 639b8e80941Smrg mtx_unlock(&drv->mutex); 640b8e80941Smrg return VA_STATUS_ERROR_INVALID_SURFACE; 641b8e80941Smrg } 642b8e80941Smrg } 643b8e80941Smrg 644b8e80941Smrg old_buf->destroy(old_buf); 645b8e80941Smrg context->target = surf->buffer; 646b8e80941Smrg } 647b8e80941Smrg 648b8e80941Smrg if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 649b8e80941Smrg coded_buf = context->coded_buf; 650b8e80941Smrg if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { 651b8e80941Smrg getEncParamPresetH264(context); 652b8e80941Smrg context->desc.h264enc.frame_num_cnt++; 653b8e80941Smrg } else if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC) 654b8e80941Smrg getEncParamPresetH265(context); 655b8e80941Smrg context->decoder->begin_frame(context->decoder, context->target, &context->desc.base); 656b8e80941Smrg context->decoder->encode_bitstream(context->decoder, context->target, 657b8e80941Smrg coded_buf->derived_surface.resource, &feedback); 658b8e80941Smrg surf->feedback = feedback; 659b8e80941Smrg surf->coded_buf = coded_buf; 660b8e80941Smrg } 661b8e80941Smrg 662b8e80941Smrg context->decoder->end_frame(context->decoder, context->target, &context->desc.base); 663b8e80941Smrg if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE && 664b8e80941Smrg u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { 665b8e80941Smrg int idr_period = context->desc.h264enc.gop_size / context->gop_coeff; 666b8e80941Smrg int p_remain_in_idr = idr_period - context->desc.h264enc.frame_num; 667b8e80941Smrg surf->frame_num_cnt = context->desc.h264enc.frame_num_cnt; 668b8e80941Smrg surf->force_flushed = false; 669b8e80941Smrg if (context->first_single_submitted) { 670b8e80941Smrg context->decoder->flush(context->decoder); 671b8e80941Smrg context->first_single_submitted = false; 672b8e80941Smrg surf->force_flushed = true; 673b8e80941Smrg } 674b8e80941Smrg if (p_remain_in_idr == 1) { 675b8e80941Smrg if ((context->desc.h264enc.frame_num_cnt % 2) != 0) { 676b8e80941Smrg context->decoder->flush(context->decoder); 677b8e80941Smrg context->first_single_submitted = true; 678b8e80941Smrg } 679b8e80941Smrg else 680b8e80941Smrg context->first_single_submitted = false; 681b8e80941Smrg surf->force_flushed = true; 682b8e80941Smrg } 683b8e80941Smrg } else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE && 684b8e80941Smrg u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC) 685b8e80941Smrg context->desc.h265enc.frame_num++; 686b8e80941Smrg mtx_unlock(&drv->mutex); 687b8e80941Smrg return VA_STATUS_SUCCESS; 688b8e80941Smrg} 689