static int ensure_surface_attribs(void) { VAStatus va_status; VASurfaceAttrib *surface_attribs; unsigned int num_image_formats, num_surface_attribs; if (va_num_surface_attribs >= 0) return va_num_surface_attribs; num_image_formats = vaMaxNumImageFormats(va_dpy); if (num_image_formats == 0) return 0; va_status = vaCreateConfig(va_dpy, VAProfileNone, VAEntrypointVideoProc, NULL, 0, &vpp_config_id); CHECK_VASTATUS(va_status, "vaCreateConfig()"); /* Guess the number of surface attributes, thus including any pixel-format supported by the VA driver */ num_surface_attribs = VASurfaceAttribCount + num_image_formats; surface_attribs = malloc(num_surface_attribs * sizeof(*surface_attribs)); if (!surface_attribs) return 0; va_status = vaQuerySurfaceAttributes(va_dpy, vpp_config_id, surface_attribs, &num_surface_attribs); if (va_status == VA_STATUS_SUCCESS) va_surface_attribs = surface_attribs; else if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) { va_surface_attribs = realloc(surface_attribs, num_surface_attribs * sizeof(*va_surface_attribs)); if (!va_surface_attribs) { free(surface_attribs); return 0; } va_status = vaQuerySurfaceAttributes(va_dpy, vpp_config_id, va_surface_attribs, &num_surface_attribs); } CHECK_VASTATUS(va_status, "vaQuerySurfaceAttributes()"); va_num_surface_attribs = num_surface_attribs; return num_surface_attribs; }
static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev, const void *hwconfig, AVHWFramesConstraints *constraints) { AVVAAPIDeviceContext *hwctx = hwdev->hwctx; const AVVAAPIHWConfig *config = hwconfig; VAAPIDeviceContext *ctx = hwdev->internal->priv; VASurfaceAttrib *attr_list = NULL; VAStatus vas; enum AVPixelFormat pix_fmt; unsigned int fourcc; int err, i, j, attr_count, pix_fmt_count; if (config) { attr_count = 0; vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id, 0, &attr_count); if (vas != VA_STATUS_SUCCESS) { av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: " "%d (%s).\n", vas, vaErrorStr(vas)); err = AVERROR(ENOSYS); goto fail; } attr_list = av_malloc(attr_count * sizeof(*attr_list)); if (!attr_list) { err = AVERROR(ENOMEM); goto fail; } vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id, attr_list, &attr_count); if (vas != VA_STATUS_SUCCESS) { av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: " "%d (%s).\n", vas, vaErrorStr(vas)); err = AVERROR(ENOSYS); goto fail; } pix_fmt_count = 0; for (i = 0; i < attr_count; i++) { switch (attr_list[i].type) { case VASurfaceAttribPixelFormat: fourcc = attr_list[i].value.value.i; pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc); if (pix_fmt != AV_PIX_FMT_NONE) { ++pix_fmt_count; } else { // Something unsupported - ignore. } break; case VASurfaceAttribMinWidth: constraints->min_width = attr_list[i].value.value.i; break; case VASurfaceAttribMinHeight: constraints->min_height = attr_list[i].value.value.i; break; case VASurfaceAttribMaxWidth: constraints->max_width = attr_list[i].value.value.i; break; case VASurfaceAttribMaxHeight: constraints->max_height = attr_list[i].value.value.i; break; } } if (pix_fmt_count == 0) { // Nothing usable found. Presumably there exists something which // works, so leave the set null to indicate unknown. constraints->valid_sw_formats = NULL; } else { constraints->valid_sw_formats = av_malloc_array(pix_fmt_count + 1, sizeof(pix_fmt)); if (!constraints->valid_sw_formats) { err = AVERROR(ENOMEM); goto fail; } for (i = j = 0; i < attr_count; i++) { if (attr_list[i].type != VASurfaceAttribPixelFormat) continue; fourcc = attr_list[i].value.value.i; pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc); if (pix_fmt != AV_PIX_FMT_NONE) constraints->valid_sw_formats[j++] = pix_fmt; } av_assert0(j == pix_fmt_count); constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE; } } else { // No configuration supplied. // Return the full set of image formats known by the implementation. constraints->valid_sw_formats = av_malloc_array(ctx->nb_formats + 1, sizeof(pix_fmt)); if (!constraints->valid_sw_formats) { err = AVERROR(ENOMEM); goto fail; } for (i = 0; i < ctx->nb_formats; i++) constraints->valid_sw_formats[i] = ctx->formats[i].pix_fmt; constraints->valid_sw_formats[i] = AV_PIX_FMT_NONE; } constraints->valid_hw_formats = av_malloc_array(2, sizeof(pix_fmt)); if (!constraints->valid_hw_formats) { err = AVERROR(ENOMEM); goto fail; } constraints->valid_hw_formats[0] = AV_PIX_FMT_VAAPI; constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; err = 0; fail: av_freep(&attr_list); return err; }
/** * gst_vaapi_get_surface_formats: * @display: a #GstVaapiDisplay * @config: a #VAConfigID * * Gets surface formats for the supplied config. * * This function will query for all the supported formats for the * supplied VA @config. * * Return value: (transfer full): a #GArray of #GstVideoFormats or %NULL */ GArray * gst_vaapi_get_surface_formats (GstVaapiDisplay * display, VAConfigID config) { VASurfaceAttrib *surface_attribs = NULL; guint i, num_surface_attribs = 0; VAStatus va_status; GArray *formats; if (config == VA_INVALID_ID) return NULL; GST_VAAPI_DISPLAY_LOCK (display); va_status = vaQuerySurfaceAttributes (GST_VAAPI_DISPLAY_VADISPLAY (display), config, NULL, &num_surface_attribs); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (va_status, "vaQuerySurfaceAttributes()")) return NULL; surface_attribs = g_malloc (num_surface_attribs * sizeof (*surface_attribs)); if (!surface_attribs) return NULL; GST_VAAPI_DISPLAY_LOCK (display); va_status = vaQuerySurfaceAttributes (GST_VAAPI_DISPLAY_VADISPLAY (display), config, surface_attribs, &num_surface_attribs); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (va_status, "vaQuerySurfaceAttributes()")) return NULL; formats = g_array_sized_new (FALSE, FALSE, sizeof (GstVideoFormat), num_surface_attribs); if (!formats) goto error; for (i = 0; i < num_surface_attribs; i++) { const VASurfaceAttrib *const attrib = &surface_attribs[i]; GstVideoFormat fmt; if (attrib->type != VASurfaceAttribPixelFormat) continue; if (!(attrib->flags & VA_SURFACE_ATTRIB_SETTABLE)) continue; fmt = gst_vaapi_video_format_from_va_fourcc (attrib->value.value.i); if (fmt == GST_VIDEO_FORMAT_UNKNOWN) continue; g_array_append_val (formats, fmt); } if (formats->len == 0) { g_array_unref (formats); formats = NULL; } g_free (surface_attribs); return formats; /* ERRORS */ error: { g_free (surface_attribs); } return NULL; }
VAConfigID vlc_vaapi_CreateConfigChecked(vlc_object_t *o, VADisplay dpy, VAProfile i_profile, VAEntrypoint entrypoint, int i_force_vlc_chroma) { int va_force_fourcc = 0; if (i_force_vlc_chroma != 0) { unsigned unused; vlc_chroma_to_vaapi(i_force_vlc_chroma, &unused, &va_force_fourcc); } if (!IsVaProfileSupported(dpy, i_profile)) { msg_Err(o, "profile(%d) is not supported", i_profile); return VA_INVALID_ID; } if (!IsEntrypointAvailable(dpy, i_profile, entrypoint)) { msg_Err(o, "entrypoint(%d) is not available", entrypoint); return VA_INVALID_ID; } /* Create a VA configuration */ VAConfigAttrib attrib = { .type = VAConfigAttribRTFormat, }; if (vaGetConfigAttributes(dpy, i_profile, entrypoint, &attrib, 1)) { msg_Err(o, "vaGetConfigAttributes failed"); return VA_INVALID_ID; } /* Not sure what to do if not, I don't have a way to test */ if ((attrib.value & (VA_RT_FORMAT_YUV420|VA_RT_FORMAT_YUV420_10BPP)) == 0) { msg_Err(o, "config doesn't support VA_RT_FORMAT_YUV420*"); return VA_INVALID_ID; } unsigned int num_sattribs; VASurfaceAttrib *sattribs = NULL; VAConfigID va_config_id = VA_INVALID_ID; VA_CALL(o, vaCreateConfig, dpy, i_profile, entrypoint, &attrib, 1, &va_config_id); if (va_force_fourcc == 0) return va_config_id; /* Fetch VASurfaceAttrib list to make sure the decoder can output NV12 */ if (vaQuerySurfaceAttributes(dpy, va_config_id, NULL, &num_sattribs) != VA_STATUS_SUCCESS) goto error; sattribs = vlc_alloc(num_sattribs, sizeof(*sattribs)); if (sattribs == NULL) goto error; if (vaQuerySurfaceAttributes(dpy, va_config_id, sattribs, &num_sattribs) != VA_STATUS_SUCCESS) goto error; for (unsigned i = 0; i < num_sattribs; ++i) { VASurfaceAttrib *sattrib = &sattribs[i]; if (sattrib->type == VASurfaceAttribPixelFormat && sattrib->flags & VA_SURFACE_ATTRIB_SETTABLE && sattrib->value.value.i == va_force_fourcc) { free(sattribs); return va_config_id; } } error: free(sattribs); if (va_config_id != VA_INVALID_ID) { msg_Err(o, "config doesn't support forced fourcc"); vlc_vaapi_DestroyConfig(o, dpy, va_config_id); } return VA_INVALID_ID; }