static int Open( vlc_va_vaapi_t *p_va, int i_codec_id ) { VAProfile i_profile, *p_profiles_list; bool b_supported_profile = false; int i_profiles_nb = 0; int i_surface_count; /* */ switch( i_codec_id ) { case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: i_profile = VAProfileMPEG2Main; i_surface_count = 2+1; break; case CODEC_ID_MPEG4: i_profile = VAProfileMPEG4AdvancedSimple; i_surface_count = 2+1; break; case CODEC_ID_WMV3: i_profile = VAProfileVC1Main; i_surface_count = 2+1; break; case CODEC_ID_VC1: i_profile = VAProfileVC1Advanced; i_surface_count = 2+1; break; case CODEC_ID_H264: i_profile = VAProfileH264High; i_surface_count = 16+1; break; default: return VLC_EGENERIC; } /* */ memset( p_va, 0, sizeof(*p_va) ); p_va->i_config_id = VA_INVALID_ID; p_va->i_context_id = VA_INVALID_ID; p_va->image.image_id = VA_INVALID_ID; /* Create a VA display */ p_va->p_display_x11 = XOpenDisplay(NULL); if( !p_va->p_display_x11 ) goto error; p_va->p_display = vaGetDisplay( p_va->p_display_x11 ); if( !p_va->p_display ) goto error; if( vaInitialize( p_va->p_display, &p_va->i_version_major, &p_va->i_version_minor ) ) goto error; /* Check if the selected profile is supported */ i_profiles_nb = vaMaxNumProfiles( p_va->p_display ); p_profiles_list = calloc( i_profiles_nb, sizeof( VAProfile ) ); if ( !p_profiles_list ) goto error; VAStatus i_status = vaQueryConfigProfiles( p_va->p_display, p_profiles_list, &i_profiles_nb ); if ( i_status == VA_STATUS_SUCCESS ) { for( int i = 0; i < i_profiles_nb; i++ ) { if ( p_profiles_list[i] == i_profile ) { b_supported_profile = true; break; } } } free( p_profiles_list ); if ( !b_supported_profile ) goto error; /* Create a VA configuration */ VAConfigAttrib attrib; memset( &attrib, 0, sizeof(attrib) ); attrib.type = VAConfigAttribRTFormat; if( vaGetConfigAttributes( p_va->p_display, i_profile, VAEntrypointVLD, &attrib, 1 ) ) goto error; /* Not sure what to do if not, I don't have a way to test */ if( (attrib.value & VA_RT_FORMAT_YUV420) == 0 ) goto error; if( vaCreateConfig( p_va->p_display, i_profile, VAEntrypointVLD, &attrib, 1, &p_va->i_config_id ) ) { p_va->i_config_id = VA_INVALID_ID; goto error; } p_va->i_surface_count = i_surface_count; if( asprintf( &p_va->va.description, "VA API version %d.%d", p_va->i_version_major, p_va->i_version_minor ) < 0 ) p_va->va.description = NULL; return VLC_SUCCESS; error: return VLC_EGENERIC; }
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; }
static av_cold int vaapi_encode_check_config(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; VAStatus vas; int i, n, err; VAProfile *profiles = NULL; VAEntrypoint *entrypoints = NULL; VAConfigAttrib attr[] = { { VAConfigAttribRateControl }, { VAConfigAttribEncMaxRefFrames }, }; n = vaMaxNumProfiles(ctx->hwctx->display); profiles = av_malloc_array(n, sizeof(VAProfile)); if (!profiles) { err = AVERROR(ENOMEM); goto fail; } vas = vaQueryConfigProfiles(ctx->hwctx->display, profiles, &n); if (vas != VA_STATUS_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n", vas, vaErrorStr(vas)); err = AVERROR(ENOSYS); goto fail; } for (i = 0; i < n; i++) { if (profiles[i] == ctx->va_profile) break; } if (i >= n) { av_log(ctx, AV_LOG_ERROR, "Encoding profile not found (%d).\n", ctx->va_profile); err = AVERROR(ENOSYS); goto fail; } n = vaMaxNumEntrypoints(ctx->hwctx->display); entrypoints = av_malloc_array(n, sizeof(VAEntrypoint)); if (!entrypoints) { err = AVERROR(ENOMEM); goto fail; } vas = vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile, entrypoints, &n); if (vas != VA_STATUS_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to query entrypoints for " "profile %u: %d (%s).\n", ctx->va_profile, vas, vaErrorStr(vas)); err = AVERROR(ENOSYS); goto fail; } for (i = 0; i < n; i++) { if (entrypoints[i] == ctx->va_entrypoint) break; } if (i >= n) { av_log(ctx, AV_LOG_ERROR, "Encoding entrypoint not found " "(%d / %d).\n", ctx->va_profile, ctx->va_entrypoint); err = AVERROR(ENOSYS); goto fail; } vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile, ctx->va_entrypoint, attr, FF_ARRAY_ELEMS(attr)); if (vas != VA_STATUS_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to fetch config " "attributes: %d (%s).\n", vas, vaErrorStr(vas)); return AVERROR(EINVAL); } for (i = 0; i < FF_ARRAY_ELEMS(attr); i++) { if (attr[i].value == VA_ATTRIB_NOT_SUPPORTED) { // Unfortunately we have to treat this as "don't know" and hope // for the best, because the Intel MJPEG encoder returns this // for all the interesting attributes. continue; } switch (attr[i].type) { case VAConfigAttribRateControl: if (!(ctx->va_rc_mode & attr[i].value)) { av_log(avctx, AV_LOG_ERROR, "Rate control mode is not " "supported: %x\n", attr[i].value); err = AVERROR(EINVAL); goto fail; } break; case VAConfigAttribEncMaxRefFrames: { unsigned int ref_l0 = attr[i].value & 0xffff; unsigned int ref_l1 = (attr[i].value >> 16) & 0xffff; if (avctx->gop_size > 1 && ref_l0 < 1) { av_log(avctx, AV_LOG_ERROR, "P frames are not " "supported (%x).\n", attr[i].value); err = AVERROR(EINVAL); goto fail; } if (avctx->max_b_frames > 0 && ref_l1 < 1) { av_log(avctx, AV_LOG_ERROR, "B frames are not " "supported (%x).\n", attr[i].value); err = AVERROR(EINVAL); goto fail; } } break; } } err = 0; fail: av_freep(&profiles); av_freep(&entrypoints); return err; }