Commit e0e2bda2 authored by wuchengli's avatar wuchengli Committed by Commit bot

vaapi: detect supported profiles in runtime.

BUG=350197,402182
TEST=Run vainfo and VEA unittest on various Intel platforms.

Review URL: https://codereview.chromium.org/603153002

Cr-Commit-Position: refs/heads/master@{#296925}
parent 6516122e
...@@ -112,20 +112,18 @@ VaapiVideoEncodeAccelerator::GetSupportedProfiles() { ...@@ -112,20 +112,18 @@ VaapiVideoEncodeAccelerator::GetSupportedProfiles() {
if (cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode)) if (cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode))
return profiles; return profiles;
SupportedProfile profile; std::vector<media::VideoCodecProfile> hw_profiles =
profile.profile = media::H264PROFILE_MAIN; VaapiWrapper::GetSupportedEncodeProfiles(
x_display_, base::Bind(&ReportToUMA, VAAPI_ERROR));
media::VideoEncodeAccelerator::SupportedProfile profile;
profile.max_resolution.SetSize(1920, 1088); profile.max_resolution.SetSize(1920, 1088);
profile.max_framerate_numerator = kDefaultFramerate; profile.max_framerate_numerator = kDefaultFramerate;
profile.max_framerate_denominator = 1; profile.max_framerate_denominator = 1;
profiles.push_back(profile); for (size_t i = 0; i < hw_profiles.size(); i++) {
profile.profile = hw_profiles[i];
// This is actually only constrained (see crbug.com/345569). profiles.push_back(profile);
profile.profile = media::H264PROFILE_BASELINE; }
profiles.push_back(profile);
profile.profile = media::H264PROFILE_HIGH;
profiles.push_back(profile);
return profiles; return profiles;
} }
......
...@@ -57,27 +57,47 @@ static const VAConfigAttrib kEncodeVAConfigAttribs[] = { ...@@ -57,27 +57,47 @@ static const VAConfigAttrib kEncodeVAConfigAttribs[] = {
VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE},
}; };
struct ProfileMap {
media::VideoCodecProfile profile;
VAProfile va_profile;
};
// A map between VideoCodecProfile and VAProfile.
static const ProfileMap kProfileMap[] = {
{media::H264PROFILE_BASELINE, VAProfileH264Baseline},
{media::H264PROFILE_MAIN, VAProfileH264Main},
// TODO(posciak): See if we can/want support other variants of
// media::H264PROFILE_HIGH*.
{media::H264PROFILE_HIGH, VAProfileH264High},
};
static std::vector<VAConfigAttrib> GetRequiredAttribs(
VaapiWrapper::CodecMode mode) {
std::vector<VAConfigAttrib> required_attribs;
required_attribs.insert(
required_attribs.end(),
kCommonVAConfigAttribs,
kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs));
if (mode == VaapiWrapper::kEncode) {
required_attribs.insert(
required_attribs.end(),
kEncodeVAConfigAttribs,
kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs));
}
return required_attribs;
}
// Maps Profile enum values to VaProfile values. // Maps Profile enum values to VaProfile values.
static VAProfile ProfileToVAProfile( static VAProfile ProfileToVAProfile(
media::VideoCodecProfile profile, media::VideoCodecProfile profile,
const std::vector<VAProfile>& supported_profiles) { const std::vector<VAProfile>& supported_profiles) {
VAProfile va_profile = VAProfileNone; VAProfile va_profile = VAProfileNone;
for (size_t i = 0; i < arraysize(kProfileMap); i++) {
switch (profile) { if (kProfileMap[i].profile == profile) {
case media::H264PROFILE_BASELINE: va_profile = kProfileMap[i].va_profile;
va_profile = VAProfileH264Baseline;
break;
case media::H264PROFILE_MAIN:
va_profile = VAProfileH264Main;
break;
// TODO(posciak): See if we can/want support other variants
// of media::H264PROFILE_HIGH*.
case media::H264PROFILE_HIGH:
va_profile = VAProfileH264High;
break;
default:
break; break;
}
} }
bool supported = std::find(supported_profiles.begin(), bool supported = std::find(supported_profiles.begin(),
...@@ -139,7 +159,36 @@ scoped_ptr<VaapiWrapper> VaapiWrapper::Create( ...@@ -139,7 +159,36 @@ scoped_ptr<VaapiWrapper> VaapiWrapper::Create(
return vaapi_wrapper.Pass(); return vaapi_wrapper.Pass();
} }
std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles(
Display* x_display,
const base::Closure& report_error_to_uma_cb) {
std::vector<media::VideoCodecProfile> supported_profiles;
scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper());
if (!wrapper->VaInitialize(x_display, report_error_to_uma_cb)) {
return supported_profiles;
}
std::vector<VAProfile> va_profiles;
if (!wrapper->GetSupportedVaProfiles(&va_profiles))
return supported_profiles;
std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode);
for (size_t i = 0; i < arraysize(kProfileMap); i++) {
VAProfile va_profile =
ProfileToVAProfile(kProfileMap[i].profile, va_profiles);
if (va_profile != VAProfileNone &&
wrapper->IsEntrypointSupported(va_profile, VAEntrypointEncSlice) &&
wrapper->AreAttribsSupported(
va_profile, VAEntrypointEncSlice, required_attribs)) {
supported_profiles.push_back(kProfileMap[i].profile);
}
}
return supported_profiles;
}
void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
base::AutoLock auto_lock(va_lock_);
VADisplayAttribute item = {VADisplayAttribRenderMode, VADisplayAttribute item = {VADisplayAttribRenderMode,
1, // At least support '_LOCAL_OVERLAY'. 1, // At least support '_LOCAL_OVERLAY'.
-1, // The maximum possible support 'ALL'. -1, // The maximum possible support 'ALL'.
...@@ -151,10 +200,8 @@ void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { ...@@ -151,10 +200,8 @@ void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default.";
} }
bool VaapiWrapper::Initialize(CodecMode mode, bool VaapiWrapper::VaInitialize(Display* x_display,
media::VideoCodecProfile profile, const base::Closure& report_error_to_uma_cb) {
Display* x_display,
const base::Closure& report_error_to_uma_cb) {
static bool vaapi_functions_initialized = PostSandboxInitialization(); static bool vaapi_functions_initialized = PostSandboxInitialization();
if (!vaapi_functions_initialized) { if (!vaapi_functions_initialized) {
DVLOG(1) << "Failed to initialize VAAPI libs"; DVLOG(1) << "Failed to initialize VAAPI libs";
...@@ -179,14 +226,18 @@ bool VaapiWrapper::Initialize(CodecMode mode, ...@@ -179,14 +226,18 @@ bool VaapiWrapper::Initialize(CodecMode mode,
DVLOG(1) << "VAAPI version < 0.34 is not supported."; DVLOG(1) << "VAAPI version < 0.34 is not supported.";
return false; return false;
} }
return true;
}
bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) {
base::AutoLock auto_lock(va_lock_);
// Query the driver for supported profiles. // Query the driver for supported profiles.
int max_profiles = vaMaxNumProfiles(va_display_); int max_profiles = vaMaxNumProfiles(va_display_);
std::vector<VAProfile> supported_profiles( std::vector<VAProfile> supported_profiles(
base::checked_cast<size_t>(max_profiles)); base::checked_cast<size_t>(max_profiles));
int num_supported_profiles; int num_supported_profiles;
va_res = vaQueryConfigProfiles( VAStatus va_res = vaQueryConfigProfiles(
va_display_, &supported_profiles[0], &num_supported_profiles); va_display_, &supported_profiles[0], &num_supported_profiles);
VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false);
if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) {
...@@ -195,23 +246,23 @@ bool VaapiWrapper::Initialize(CodecMode mode, ...@@ -195,23 +246,23 @@ bool VaapiWrapper::Initialize(CodecMode mode,
} }
supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles));
*profiles = supported_profiles;
return true;
}
VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); bool VaapiWrapper::IsEntrypointSupported(VAProfile va_profile,
if (va_profile == VAProfileNone) { VAEntrypoint entrypoint) {
DVLOG(1) << "Unsupported profile"; base::AutoLock auto_lock(va_lock_);
return false;
}
// Query the driver for supported entrypoints. // Query the driver for supported entrypoints.
int max_entrypoints = vaMaxNumEntrypoints(va_display_); int max_entrypoints = vaMaxNumEntrypoints(va_display_);
std::vector<VAEntrypoint> supported_entrypoints( std::vector<VAEntrypoint> supported_entrypoints(
base::checked_cast<size_t>(max_entrypoints)); base::checked_cast<size_t>(max_entrypoints));
int num_supported_entrypoints; int num_supported_entrypoints;
va_res = vaQueryConfigEntrypoints(va_display_, VAStatus va_res = vaQueryConfigEntrypoints(va_display_,
va_profile, va_profile,
&supported_entrypoints[0], &supported_entrypoints[0],
&num_supported_entrypoints); &num_supported_entrypoints);
VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false);
if (num_supported_entrypoints < 0 || if (num_supported_entrypoints < 0 ||
num_supported_entrypoints > max_entrypoints) { num_supported_entrypoints > max_entrypoints) {
...@@ -220,34 +271,26 @@ bool VaapiWrapper::Initialize(CodecMode mode, ...@@ -220,34 +271,26 @@ bool VaapiWrapper::Initialize(CodecMode mode,
return false; return false;
} }
VAEntrypoint entrypoint =
(mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
if (std::find(supported_entrypoints.begin(), if (std::find(supported_entrypoints.begin(),
supported_entrypoints.end(), supported_entrypoints.end(),
entrypoint) == supported_entrypoints.end()) { entrypoint) == supported_entrypoints.end()) {
DVLOG(1) << "Unsupported entrypoint"; DVLOG(1) << "Unsupported entrypoint";
return false; return false;
} }
return true;
}
bool VaapiWrapper::AreAttribsSupported(
VAProfile va_profile,
VAEntrypoint entrypoint,
const std::vector<VAConfigAttrib>& required_attribs) {
base::AutoLock auto_lock(va_lock_);
// Query the driver for required attributes. // Query the driver for required attributes.
std::vector<VAConfigAttrib> required_attribs;
required_attribs.insert(
required_attribs.end(),
kCommonVAConfigAttribs,
kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs));
if (mode == kEncode) {
required_attribs.insert(
required_attribs.end(),
kEncodeVAConfigAttribs,
kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs));
}
std::vector<VAConfigAttrib> attribs = required_attribs; std::vector<VAConfigAttrib> attribs = required_attribs;
for (size_t i = 0; i < required_attribs.size(); ++i) for (size_t i = 0; i < required_attribs.size(); ++i)
attribs[i].value = 0; attribs[i].value = 0;
va_res = vaGetConfigAttributes( VAStatus va_res = vaGetConfigAttributes(
va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); va_display_, va_profile, entrypoint, &attribs[0], attribs.size());
VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false);
...@@ -260,15 +303,40 @@ bool VaapiWrapper::Initialize(CodecMode mode, ...@@ -260,15 +303,40 @@ bool VaapiWrapper::Initialize(CodecMode mode,
return false; return false;
} }
} }
return true;
}
bool VaapiWrapper::Initialize(CodecMode mode,
media::VideoCodecProfile profile,
Display* x_display,
const base::Closure& report_error_to_uma_cb) {
if (!VaInitialize(x_display, report_error_to_uma_cb))
return false;
std::vector<VAProfile> supported_va_profiles;
if (!GetSupportedVaProfiles(&supported_va_profiles))
return false;
VAProfile va_profile = ProfileToVAProfile(profile, supported_va_profiles);
if (va_profile == VAProfileNone) {
DVLOG(1) << "Unsupported profile";
return false;
}
VAEntrypoint entrypoint =
(mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
if (!IsEntrypointSupported(va_profile, entrypoint))
return false;
std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode);
if (!AreAttribsSupported(va_profile, entrypoint, required_attribs))
return false;
TryToSetVADisplayAttributeToLocalGPU(); TryToSetVADisplayAttributeToLocalGPU();
va_res = vaCreateConfig(va_display_, base::AutoLock auto_lock(va_lock_);
va_profile, VAStatus va_res = vaCreateConfig(va_display_,
entrypoint, va_profile,
&required_attribs[0], entrypoint,
required_attribs.size(), &required_attribs[0],
&va_config_id_); required_attribs.size(),
&va_config_id_);
VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false);
return true; return true;
......
...@@ -50,6 +50,11 @@ class CONTENT_EXPORT VaapiWrapper { ...@@ -50,6 +50,11 @@ class CONTENT_EXPORT VaapiWrapper {
Display* x_display, Display* x_display,
const base::Closure& report_error_to_uma_cb); const base::Closure& report_error_to_uma_cb);
// Return the supported encode profiles.
static std::vector<media::VideoCodecProfile> GetSupportedEncodeProfiles(
Display* x_display,
const base::Closure& report_error_to_uma_cb);
~VaapiWrapper(); ~VaapiWrapper();
// Create |num_surfaces| backing surfaces in driver for VASurfaces, each // Create |num_surfaces| backing surfaces in driver for VASurfaces, each
...@@ -140,8 +145,15 @@ class CONTENT_EXPORT VaapiWrapper { ...@@ -140,8 +145,15 @@ class CONTENT_EXPORT VaapiWrapper {
bool Initialize(CodecMode mode, bool Initialize(CodecMode mode,
media::VideoCodecProfile profile, media::VideoCodecProfile profile,
Display* x_display, Display* x_display,
const base::Closure& report_error__to_uma_cb); const base::Closure& report_error_to_uma_cb);
void Deinitialize(); void Deinitialize();
bool VaInitialize(Display* x_display,
const base::Closure& report_error_to_uma_cb);
bool GetSupportedVaProfiles(std::vector<VAProfile>* profiles);
bool IsEntrypointSupported(VAProfile va_profile, VAEntrypoint entrypoint);
bool AreAttribsSupported(VAProfile va_profile,
VAEntrypoint entrypoint,
const std::vector<VAConfigAttrib>& required_attribs);
// Execute pending job in hardware and destroy pending buffers. Return false // Execute pending job in hardware and destroy pending buffers. Return false
// if vaapi driver refuses to accept parameter or slice buffers submitted // if vaapi driver refuses to accept parameter or slice buffers submitted
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment