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_screen.h" 30 31#include "util/u_video.h" 32#include "util/u_memory.h" 33 34#include "vl/vl_winsys.h" 35 36#include "va_private.h" 37 38#include "util/u_handle_table.h" 39 40DEBUG_GET_ONCE_BOOL_OPTION(mpeg4, "VAAPI_MPEG4_ENABLED", false) 41 42VAStatus 43vlVaQueryConfigProfiles(VADriverContextP ctx, VAProfile *profile_list, int *num_profiles) 44{ 45 struct pipe_screen *pscreen; 46 enum pipe_video_profile p; 47 VAProfile vap; 48 49 if (!ctx) 50 return VA_STATUS_ERROR_INVALID_CONTEXT; 51 52 *num_profiles = 0; 53 54 pscreen = VL_VA_PSCREEN(ctx); 55 for (p = PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; p <= PIPE_VIDEO_PROFILE_AV1_MAIN; ++p) { 56 if (u_reduce_video_profile(p) == PIPE_VIDEO_FORMAT_MPEG4 && !debug_get_option_mpeg4()) 57 continue; 58 59 if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_SUPPORTED) || 60 pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) { 61 vap = PipeToProfile(p); 62 if (vap != VAProfileNone) 63 profile_list[(*num_profiles)++] = vap; 64 } 65 } 66 67 /* Support postprocessing through vl_compositor */ 68 profile_list[(*num_profiles)++] = VAProfileNone; 69 70 return VA_STATUS_SUCCESS; 71} 72 73VAStatus 74vlVaQueryConfigEntrypoints(VADriverContextP ctx, VAProfile profile, 75 VAEntrypoint *entrypoint_list, int *num_entrypoints) 76{ 77 struct pipe_screen *pscreen; 78 enum pipe_video_profile p; 79 80 if (!ctx) 81 return VA_STATUS_ERROR_INVALID_CONTEXT; 82 83 *num_entrypoints = 0; 84 85 if (profile == VAProfileNone) { 86 entrypoint_list[(*num_entrypoints)++] = VAEntrypointVideoProc; 87 return VA_STATUS_SUCCESS; 88 } 89 90 p = ProfileToPipe(profile); 91 if (p == PIPE_VIDEO_PROFILE_UNKNOWN || 92 (u_reduce_video_profile(p) == PIPE_VIDEO_FORMAT_MPEG4 && 93 !debug_get_option_mpeg4())) 94 return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; 95 96 pscreen = VL_VA_PSCREEN(ctx); 97 if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 98 PIPE_VIDEO_CAP_SUPPORTED)) 99 entrypoint_list[(*num_entrypoints)++] = VAEntrypointVLD; 100 101 if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_ENCODE, 102 PIPE_VIDEO_CAP_SUPPORTED)) 103 entrypoint_list[(*num_entrypoints)++] = VAEntrypointEncSlice; 104 105 if (*num_entrypoints == 0) 106 return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; 107 108 assert(*num_entrypoints <= ctx->max_entrypoints); 109 110 return VA_STATUS_SUCCESS; 111} 112 113VAStatus 114vlVaGetConfigAttributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, 115 VAConfigAttrib *attrib_list, int num_attribs) 116{ 117 struct pipe_screen *pscreen; 118 int i; 119 120 if (!ctx) 121 return VA_STATUS_ERROR_INVALID_CONTEXT; 122 123 pscreen = VL_VA_PSCREEN(ctx); 124 125 for (i = 0; i < num_attribs; ++i) { 126 unsigned int value; 127 if ((entrypoint == VAEntrypointVLD) && 128 (pscreen->get_video_param(pscreen, ProfileToPipe(profile), 129 PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_SUPPORTED))) { 130 switch (attrib_list[i].type) { 131 case VAConfigAttribRTFormat: 132 value = VA_RT_FORMAT_YUV420 | VA_RT_FORMAT_YUV422; 133 if (pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P010, 134 ProfileToPipe(profile), 135 PIPE_VIDEO_ENTRYPOINT_BITSTREAM) || 136 pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P016, 137 ProfileToPipe(profile), 138 PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) 139 value |= VA_RT_FORMAT_YUV420_10BPP; 140 break; 141 default: 142 value = VA_ATTRIB_NOT_SUPPORTED; 143 break; 144 } 145 } else if ((entrypoint == VAEntrypointEncSlice) && 146 (pscreen->get_video_param(pscreen, ProfileToPipe(profile), 147 PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED))) { 148 switch (attrib_list[i].type) { 149 case VAConfigAttribRTFormat: 150 value = VA_RT_FORMAT_YUV420; 151 if (pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P010, 152 ProfileToPipe(profile), 153 PIPE_VIDEO_ENTRYPOINT_ENCODE) || 154 pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P016, 155 ProfileToPipe(profile), 156 PIPE_VIDEO_ENTRYPOINT_ENCODE)) 157 value |= VA_RT_FORMAT_YUV420_10BPP; 158 break; 159 case VAConfigAttribRateControl: 160 value = VA_RC_CQP | VA_RC_CBR | VA_RC_VBR; 161 break; 162 case VAConfigAttribEncRateControlExt: 163 value = pscreen->get_video_param(pscreen, ProfileToPipe(profile), 164 PIPE_VIDEO_ENTRYPOINT_ENCODE, 165 PIPE_VIDEO_CAP_MAX_TEMPORAL_LAYERS); 166 if (value > 0) { 167 value -= 1; 168 value |= (1 << 8); /* temporal_layer_bitrate_control_flag */ 169 } 170 break; 171 case VAConfigAttribEncPackedHeaders: 172 value = VA_ENC_PACKED_HEADER_NONE; 173 if (u_reduce_video_profile(ProfileToPipe(profile)) == PIPE_VIDEO_FORMAT_MPEG4_AVC || 174 u_reduce_video_profile(ProfileToPipe(profile)) == PIPE_VIDEO_FORMAT_HEVC) 175 value |= VA_ENC_PACKED_HEADER_SEQUENCE; 176 break; 177 case VAConfigAttribEncMaxRefFrames: 178 value = 1; 179 break; 180 default: 181 value = VA_ATTRIB_NOT_SUPPORTED; 182 break; 183 } 184 } else if (entrypoint == VAEntrypointVideoProc) { 185 switch (attrib_list[i].type) { 186 case VAConfigAttribRTFormat: 187 value = (VA_RT_FORMAT_YUV420 | 188 VA_RT_FORMAT_YUV420_10BPP | 189 VA_RT_FORMAT_RGB32); 190 break; 191 default: 192 value = VA_ATTRIB_NOT_SUPPORTED; 193 break; 194 } 195 } else { 196 value = VA_ATTRIB_NOT_SUPPORTED; 197 } 198 attrib_list[i].value = value; 199 } 200 201 return VA_STATUS_SUCCESS; 202} 203 204VAStatus 205vlVaCreateConfig(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, 206 VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id) 207{ 208 vlVaDriver *drv; 209 vlVaConfig *config; 210 struct pipe_screen *pscreen; 211 enum pipe_video_profile p; 212 unsigned int supported_rt_formats; 213 214 if (!ctx) 215 return VA_STATUS_ERROR_INVALID_CONTEXT; 216 217 drv = VL_VA_DRIVER(ctx); 218 219 if (!drv) 220 return VA_STATUS_ERROR_INVALID_CONTEXT; 221 222 config = CALLOC(1, sizeof(vlVaConfig)); 223 if (!config) 224 return VA_STATUS_ERROR_ALLOCATION_FAILED; 225 226 if (profile == VAProfileNone) { 227 if (entrypoint != VAEntrypointVideoProc) { 228 FREE(config); 229 return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; 230 } 231 232 config->entrypoint = PIPE_VIDEO_ENTRYPOINT_UNKNOWN; 233 config->profile = PIPE_VIDEO_PROFILE_UNKNOWN; 234 supported_rt_formats = VA_RT_FORMAT_YUV420 | 235 VA_RT_FORMAT_YUV420_10BPP | 236 VA_RT_FORMAT_RGB32; 237 for (int i = 0; i < num_attribs; i++) { 238 if (attrib_list[i].type == VAConfigAttribRTFormat) { 239 if (attrib_list[i].value & supported_rt_formats) { 240 config->rt_format = attrib_list[i].value; 241 } else { 242 FREE(config); 243 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; 244 } 245 } else { 246 /*other attrib_types are not supported.*/ 247 FREE(config); 248 return VA_STATUS_ERROR_INVALID_VALUE; 249 } 250 } 251 252 /* Default value if not specified in the input attributes. */ 253 if (!config->rt_format) 254 config->rt_format = supported_rt_formats; 255 256 mtx_lock(&drv->mutex); 257 *config_id = handle_table_add(drv->htab, config); 258 mtx_unlock(&drv->mutex); 259 return VA_STATUS_SUCCESS; 260 } 261 262 p = ProfileToPipe(profile); 263 if (p == PIPE_VIDEO_PROFILE_UNKNOWN || 264 (u_reduce_video_profile(p) == PIPE_VIDEO_FORMAT_MPEG4 && 265 !debug_get_option_mpeg4())) { 266 FREE(config); 267 return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; 268 } 269 270 pscreen = VL_VA_PSCREEN(ctx); 271 272 switch (entrypoint) { 273 case VAEntrypointVLD: 274 supported_rt_formats = VA_RT_FORMAT_YUV420 | VA_RT_FORMAT_YUV422; 275 if (!pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 276 PIPE_VIDEO_CAP_SUPPORTED)) { 277 FREE(config); 278 return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; 279 } 280 281 config->entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; 282 break; 283 284 case VAEntrypointEncSlice: 285 supported_rt_formats = VA_RT_FORMAT_YUV420; 286 if (!pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_ENCODE, 287 PIPE_VIDEO_CAP_SUPPORTED)) { 288 FREE(config); 289 return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; 290 } 291 292 config->entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; 293 break; 294 295 default: 296 FREE(config); 297 return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; 298 } 299 300 config->profile = p; 301 if (pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P010, p, 302 config->entrypoint) || 303 pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P016, p, 304 config->entrypoint)) 305 supported_rt_formats |= VA_RT_FORMAT_YUV420_10BPP; 306 307 for (int i = 0; i <num_attribs ; i++) { 308 if (attrib_list[i].type != VAConfigAttribRTFormat && 309 entrypoint == VAEntrypointVLD ) { 310 FREE(config); 311 return VA_STATUS_ERROR_INVALID_VALUE; 312 } 313 if (attrib_list[i].type == VAConfigAttribRateControl) { 314 if (attrib_list[i].value == VA_RC_CBR) 315 config->rc = PIPE_H2645_ENC_RATE_CONTROL_METHOD_CONSTANT; 316 else if (attrib_list[i].value == VA_RC_VBR) 317 config->rc = PIPE_H2645_ENC_RATE_CONTROL_METHOD_VARIABLE; 318 else if (attrib_list[i].value == VA_RC_CQP) 319 config->rc = PIPE_H2645_ENC_RATE_CONTROL_METHOD_DISABLE; 320 else { 321 FREE(config); 322 return VA_STATUS_ERROR_INVALID_VALUE; 323 } 324 } 325 if (attrib_list[i].type == VAConfigAttribRTFormat) { 326 if (attrib_list[i].value & supported_rt_formats) { 327 config->rt_format = attrib_list[i].value; 328 } else { 329 FREE(config); 330 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; 331 } 332 } 333 if (attrib_list[i].type == VAConfigAttribEncPackedHeaders) { 334 if (attrib_list[i].value > 1 || 335 config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) { 336 FREE(config); 337 return VA_STATUS_ERROR_INVALID_VALUE; 338 } 339 } 340 } 341 342 /* Default value if not specified in the input attributes. */ 343 if (!config->rt_format) 344 config->rt_format = supported_rt_formats; 345 346 mtx_lock(&drv->mutex); 347 *config_id = handle_table_add(drv->htab, config); 348 mtx_unlock(&drv->mutex); 349 350 return VA_STATUS_SUCCESS; 351} 352 353VAStatus 354vlVaDestroyConfig(VADriverContextP ctx, VAConfigID config_id) 355{ 356 vlVaDriver *drv; 357 vlVaConfig *config; 358 359 if (!ctx) 360 return VA_STATUS_ERROR_INVALID_CONTEXT; 361 362 drv = VL_VA_DRIVER(ctx); 363 364 if (!drv) 365 return VA_STATUS_ERROR_INVALID_CONTEXT; 366 367 mtx_lock(&drv->mutex); 368 config = handle_table_get(drv->htab, config_id); 369 370 if (!config) { 371 mtx_unlock(&drv->mutex); 372 return VA_STATUS_ERROR_INVALID_CONFIG; 373 } 374 375 FREE(config); 376 handle_table_remove(drv->htab, config_id); 377 mtx_unlock(&drv->mutex); 378 379 return VA_STATUS_SUCCESS; 380} 381 382VAStatus 383vlVaQueryConfigAttributes(VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, 384 VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs) 385{ 386 vlVaDriver *drv; 387 vlVaConfig *config; 388 389 if (!ctx) 390 return VA_STATUS_ERROR_INVALID_CONTEXT; 391 392 drv = VL_VA_DRIVER(ctx); 393 394 if (!drv) 395 return VA_STATUS_ERROR_INVALID_CONTEXT; 396 397 mtx_lock(&drv->mutex); 398 config = handle_table_get(drv->htab, config_id); 399 mtx_unlock(&drv->mutex); 400 401 if (!config) 402 return VA_STATUS_ERROR_INVALID_CONFIG; 403 404 *profile = PipeToProfile(config->profile); 405 406 switch (config->entrypoint) { 407 case PIPE_VIDEO_ENTRYPOINT_BITSTREAM: 408 *entrypoint = VAEntrypointVLD; 409 break; 410 case PIPE_VIDEO_ENTRYPOINT_ENCODE: 411 *entrypoint = VAEntrypointEncSlice; 412 break; 413 case PIPE_VIDEO_ENTRYPOINT_UNKNOWN: 414 *entrypoint = VAEntrypointVideoProc; 415 break; 416 default: 417 return VA_STATUS_ERROR_INVALID_CONFIG; 418 } 419 420 *num_attribs = 1; 421 attrib_list[0].type = VAConfigAttribRTFormat; 422 attrib_list[0].value = config->rt_format; 423 424 return VA_STATUS_SUCCESS; 425} 426