VaApi::VaApi() { init = true; auto xdpy = QX11Info::display(); VADisplay display = m_display = vaGetDisplayGLX(xdpy); if (!check(display ? VA_STATUS_SUCCESS : VA_STATUS_ERROR_UNIMPLEMENTED, "Cannot create VADisplay.")) return; int major, minor; if (!check(vaInitialize(m_display, &major, &minor), "Cannot initialize VA-API.")) return; auto size = vaMaxNumProfiles(display); m_profiles.resize(size); if (!check(vaQueryConfigProfiles(display, m_profiles.data(), &size), "No available profiles.")) return; m_profiles.resize(size); for (auto profile : m_profiles) { int size = vaMaxNumEntrypoints(display); QVector<VAEntrypoint> entries(size); if (!isSuccess(vaQueryConfigEntrypoints(display, profile, entries.data(), &size))) continue; entries.resize(size); m_entries.insert(profile, entries); } initCodecs(); #ifdef USE_VAVPP initFilters(); #endif _Debug("VA-API is initialized."); ok = true; }
static bool IsEntrypointAvailable(VADisplay dpy, VAProfile i_profile, VAEntrypoint entrypoint) { VAEntrypoint * entrypoints; int num_entrypoints = vaMaxNumEntrypoints(dpy); bool ret = false; if (num_entrypoints <= 0) return false; entrypoints = vlc_alloc(num_entrypoints, sizeof(VAEntrypoint)); if (!entrypoints) return false; VAStatus status = vaQueryConfigEntrypoints(dpy, i_profile, entrypoints, &num_entrypoints); if (status != VA_STATUS_SUCCESS) goto error; for (int i = 0; i < num_entrypoints; ++i) if (entrypoint == entrypoints[i]) { ret = true; break; } error: free(entrypoints); return ret; }
static int has_entrypoint(VAAPIContext *vaapi, VAProfile profile, VAEntrypoint entrypoint) { VAStatus status; int i; if (!vaapi->entrypoints || vaapi->n_entrypoints == 0) { vaapi->entrypoints = calloc(vaMaxNumEntrypoints(vaapi->display), sizeof(vaapi->entrypoints[0])); status = vaQueryConfigEntrypoints(vaapi->display, profile, vaapi->entrypoints, &vaapi->n_entrypoints); if (!vaapi_check_status(status, "vaQueryConfigEntrypoints()")) return 0; D(bug("%d entrypoints available for %s\n", vaapi->n_entrypoints, string_of_VAProfile(profile))); for (i = 0; i < vaapi->n_entrypoints; i++) D(bug(" %s\n", string_of_VAEntrypoint(vaapi->entrypoints[i]))); } for (i = 0; i < vaapi->n_entrypoints; i++) { if (vaapi->entrypoints[i] == entrypoint) return 1; } return 0; }
bool VAAPIContext::InitProfiles(void) { if (!(codec_is_vaapi_hw(m_codec)) || !m_ctx.display) return false; MythXLocker locker(m_display->m_x_disp); int max_profiles, max_entrypoints; VAProfile profile_wanted = preferredProfile(m_codec); if (profile_wanted == VAProfileMPEG2Simple) { LOG(VB_PLAYBACK, LOG_ERR, LOC + "Codec is not supported."); return false; } VAProfile profile_found = VAProfileMPEG2Simple; // unsupported value VAEntrypoint entry_found = VAEntrypointEncSlice; // unsupported value max_profiles = vaMaxNumProfiles(m_ctx.display); max_entrypoints = vaMaxNumEntrypoints(m_ctx.display); VAProfile *profiles = new VAProfile[max_profiles]; VAEntrypoint *entries = new VAEntrypoint[max_entrypoints]; static bool debugged = false; if (profiles && entries) { INIT_ST; int act_profiles, act_entries; va_status = vaQueryConfigProfiles(m_ctx.display, profiles, &act_profiles); CHECK_ST; if (ok && act_profiles > 0) { for (int i = 0; i < act_profiles; i++) { va_status = vaQueryConfigEntrypoints(m_ctx.display, profiles[i], entries, &act_entries); if (va_status == VA_STATUS_SUCCESS && act_entries > 0) { if (profiles[i] == profile_wanted) { profile_found = profile_wanted; for (int j = 0; j < act_entries; j++) if (entries[j] < entry_found) entry_found = entries[j]; } if (!debugged) { QString entrylist = "Entrypoints: "; for (int j = 0; j < act_entries; j++) entrylist += entryToString(entries[j]); LOG(VB_GENERAL, LOG_INFO, LOC + QString("Profile: %1 %2") .arg(profileToString(profiles[i])) .arg(entrylist)); } } } } debugged = true; } delete [] profiles; delete [] entries; LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Desired profile for '%1': %2") .arg(toString(m_codec)).arg(profileToString(profile_wanted))); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Found profile %1 with entry %2") .arg(profileToString(profile_found)).arg(entryToString(entry_found))); if (profile_wanted != profile_found) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to find supported profile."); return false; } if (entry_found > VAEntrypointVLD) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to find suitable entry point."); return false; } m_vaProfile = profile_wanted; m_vaEntrypoint = entry_found; if (VAEntrypointVLD == m_vaEntrypoint) m_pix_fmt = PIX_FMT_VAAPI_VLD; return true; }
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; }