Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1144)

Unified Diff: content/common/gpu/media/vaapi_wrapper.cc

Issue 872623002: VaapiVEA: Get maximum resolution from libva (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nits Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/common/gpu/media/vaapi_wrapper.cc
diff --git a/content/common/gpu/media/vaapi_wrapper.cc b/content/common/gpu/media/vaapi_wrapper.cc
index 588fee3981e59072c6118996099258acaa51e82b..464f816e07bd078591336c032d537204592531e4 100644
--- a/content/common/gpu/media/vaapi_wrapper.cc
+++ b/content/common/gpu/media/vaapi_wrapper.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/lazy_instance.h"
Pawel Osciak 2015/03/02 11:00:20 Already in the header.
henryhsu 2015/03/03 10:48:01 Done.
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/sys_info.h"
@@ -56,6 +57,11 @@ using content_common_gpu_media::StubPathMap;
namespace content {
+const int kDefaultFramerate = 30;
wuchengli 2015/03/02 07:10:12 s/kDefaultFramerate/kMaxFramerate/. in VaapiVDA, i
Pawel Osciak 2015/03/02 11:00:20 Please add a comment saying that this is an arbitr
henryhsu 2015/03/03 10:48:02 Done.
henryhsu 2015/03/03 10:48:02 Done.
+
+base::LazyInstance<VaapiWrapper::LazyProfileInfo>
+ VaapiWrapper::profile_info_ = LAZY_INSTANCE_INITIALIZER;
+
// Config attributes common for both encode and decode.
static const VAConfigAttrib kCommonVAConfigAttribs[] = {
{VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420},
@@ -69,17 +75,25 @@ static const VAConfigAttrib kEncodeVAConfigAttribs[] = {
};
struct ProfileMap {
- media::VideoCodecProfile profile;
VAProfile va_profile;
+ media::VideoCodecProfile profile;
};
-// A map between VideoCodecProfile and VAProfile.
+// A map between VAProfile and VideoCodecProfile.
static const ProfileMap kProfileMap[] = {
- {media::H264PROFILE_BASELINE, VAProfileH264Baseline},
- {media::H264PROFILE_MAIN, VAProfileH264Main},
+ {VAProfileH264Baseline, media::H264PROFILE_BASELINE},
+ {VAProfileH264Main, media::H264PROFILE_MAIN},
// TODO(posciak): See if we can/want support other variants of
// media::H264PROFILE_HIGH*.
- {media::H264PROFILE_HIGH, VAProfileH264High},
+ {VAProfileH264High, media::H264PROFILE_HIGH},
+ // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips
+ // the information whether the profile is constrained or not, so we have no
+ // way to know here. We try all va profiles with matched profile in
+ // CreateForVideoCodec. So for H264PROFILE_BASELINE, we try
+ // VAProfileH264Baseline first. If it is not supported, try constrained
+ // baseline and hope this is what it actually is. (which in practice is
+ // true for a great majority of cases).
+ {VAProfileH264ConstrainedBaseline, media::H264PROFILE_BASELINE},
wuchengli 2015/03/02 07:28:32 Move this below VAProfileH264Baseline so two H264P
Pawel Osciak 2015/03/02 11:00:20 How does fallback to Constrained work now?
henryhsu 2015/03/03 10:48:01 Done.
henryhsu 2015/03/03 10:48:01 Change back to original way.
};
static std::vector<VAConfigAttrib> GetRequiredAttribs(
@@ -98,39 +112,16 @@ static std::vector<VAConfigAttrib> GetRequiredAttribs(
return required_attribs;
}
-// Maps Profile enum values to VaProfile values.
-static VAProfile ProfileToVAProfile(
- media::VideoCodecProfile profile,
- const std::vector<VAProfile>& supported_profiles) {
-
- VAProfile va_profile = VAProfileNone;
+// Maps VaProfile enum values to Profile values.
+static media::VideoCodecProfile VAProfileToProfile(VAProfile va_profile) {
+ media::VideoCodecProfile profile = media::VIDEO_CODEC_PROFILE_UNKNOWN;
for (size_t i = 0; i < arraysize(kProfileMap); i++) {
- if (kProfileMap[i].profile == profile) {
- va_profile = kProfileMap[i].va_profile;
+ if (kProfileMap[i].va_profile == va_profile) {
+ profile = kProfileMap[i].profile;
break;
}
}
-
- bool supported = std::find(supported_profiles.begin(),
- supported_profiles.end(),
- va_profile) != supported_profiles.end();
-
- if (!supported && va_profile == VAProfileH264Baseline) {
- // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips
- // the information whether the profile is constrained or not, so we have no
- // way to know here. Try for baseline first, but if it is not supported,
- // try constrained baseline and hope this is what it actually is
- // (which in practice is true for a great majority of cases).
- if (std::find(supported_profiles.begin(),
- supported_profiles.end(),
- VAProfileH264ConstrainedBaseline) !=
- supported_profiles.end()) {
- va_profile = VAProfileH264ConstrainedBaseline;
- DVLOG(1) << "Falling back to constrained baseline profile.";
- }
- }
-
- return va_profile;
+ return profile;
}
VASurface::VASurface(VASurfaceID va_surface_id,
@@ -162,6 +153,7 @@ VaapiWrapper::~VaapiWrapper() {
Deinitialize();
}
+// static
scoped_ptr<VaapiWrapper> VaapiWrapper::Create(
CodecMode mode,
VAProfile va_profile,
@@ -170,12 +162,16 @@ scoped_ptr<VaapiWrapper> VaapiWrapper::Create(
if (!vaapi_wrapper->VaInitialize(report_error_to_uma_cb))
return nullptr;
- if (!vaapi_wrapper->Initialize(mode, va_profile))
+
+ if (!vaapi_wrapper->Initialize(mode, va_profile)) {
+ DVLOG(1) << "Unsupported va profile: " << va_profile;
return nullptr;
+ }
return vaapi_wrapper.Pass();
}
+// static
scoped_ptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec(
CodecMode mode,
media::VideoCodecProfile profile,
@@ -185,42 +181,44 @@ scoped_ptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec(
if (!vaapi_wrapper->VaInitialize(report_error_to_uma_cb))
return nullptr;
- std::vector<VAProfile> supported_va_profiles;
- if (!vaapi_wrapper->GetSupportedVaProfiles(&supported_va_profiles))
- return nullptr;
-
- VAProfile va_profile = ProfileToVAProfile(profile, supported_va_profiles);
- if (!vaapi_wrapper->Initialize(mode, va_profile))
- return nullptr;
-
- return vaapi_wrapper.Pass();
-}
-
-std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles(
- const base::Closure& report_error_to_uma_cb) {
- std::vector<media::VideoCodecProfile> supported_profiles;
-
- scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper());
- if (!wrapper->VaInitialize(report_error_to_uma_cb)) {
- return supported_profiles;
+ for (size_t i = 0; i < arraysize(kProfileMap); ++i) {
+ if (kProfileMap[i].profile == profile &&
+ vaapi_wrapper->Initialize(mode, kProfileMap[i].va_profile))
+ return vaapi_wrapper.Pass();
}
+ DVLOG(1) << "Unsupported profile: " << profile;
Pawel Osciak 2015/03/02 11:00:20 This may also fail if profile is supported, but va
henryhsu 2015/03/03 10:48:02 Done.
+ return nullptr;
+}
- 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);
+// static
+std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+VaapiWrapper::GetSupportedEncodeProfiles() {
+ std::vector<ProfileInfo> encode_profile_info =
wuchengli 2015/03/02 07:10:12 s/encode_profile_info/encode_profile_infos/
henryhsu 2015/03/03 10:48:01 Done.
+ profile_info_.Get().GetSupportedProfileInfos(kEncode);
+ std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles;
+ media::VideoEncodeAccelerator::SupportedProfile profile;
+
+ for (size_t i = 0; i < encode_profile_info.size(); ++i) {
+ media::VideoCodecProfile hw_profile = VAProfileToProfile(
wuchengli 2015/03/02 07:28:32 As discussed, this can add two media::H264PROFILE_
henryhsu 2015/03/03 10:48:01 Done.
+ encode_profile_info[i].va_profile);
+ if (hw_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN) {
+ profile.profile = hw_profile;
+ profile.max_resolution = encode_profile_info[i].max_resolution;
+ profile.max_framerate_numerator = kDefaultFramerate;
+ profile.max_framerate_denominator = 1;
+ profiles.push_back(profile);
}
}
- return supported_profiles;
+ return profiles;
+}
+
+// static
+std::vector<VaapiWrapper::ProfileInfo>
wuchengli 2015/03/02 07:10:12 InitSupportedProfileInfos should be renamed.
henryhsu 2015/03/03 10:48:01 Done.
+VaapiWrapper::InitSupportedProfileInfos() {
wuchengli 2015/03/02 07:10:12 How about adding CodecMode parameter to InitSuppor
henryhsu 2015/03/03 10:48:01 Done.
+ scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper());
+ if (!vaapi_wrapper->VaInitialize(base::Bind(&base::DoNothing)))
+ return std::vector<ProfileInfo>();
+ return vaapi_wrapper->GetSupportedProfileInfos();
}
void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
@@ -236,6 +234,44 @@ void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default.";
}
+std::vector<VaapiWrapper::ProfileInfo>
+VaapiWrapper::GetSupportedProfileInfos() {
+ std::vector<ProfileInfo> supported_profiles;
wuchengli 2015/03/02 07:10:12 s/supported_profiles/supported_profile_infos/. Let
henryhsu 2015/03/03 10:48:02 Done.
+ std::vector<VAProfile> va_profiles;
+ if (!GetSupportedVaProfiles(&va_profiles))
+ return supported_profiles;
+
+ ProfileInfo profile_info;
+ std::vector<CodecMode> modes({kDecode, kEncode});
+ for (size_t i = 0; i < modes.size(); ++i) {
+ std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(modes[i]);
+ VAEntrypoint entrypoint =
+ (modes[i] == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD);
+ for (size_t j = 0; j < va_profiles.size(); ++j) {
+ if (!IsEntrypointSupported(va_profiles[j], entrypoint))
+ continue;
+ if (!AreAttribsSupported(va_profiles[j], entrypoint, required_attribs))
+ continue;
+ VAConfigID config_id;
+ VAStatus va_res = vaCreateConfig(
+ va_display_,
+ va_profiles[j],
+ entrypoint,
+ &required_attribs[0],
+ required_attribs.size(),
+ &config_id);
+ if (va_res != VA_STATUS_SUCCESS)
+ continue;
+ if (!GetVaCodecMaxResolution(config_id, &profile_info.max_resolution))
+ continue;
+ profile_info.va_profile = va_profiles[j];
+ profile_info.mode = modes[i];
+ supported_profiles.push_back(profile_info);
+ }
+ }
+ return supported_profiles;
+}
+
bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) {
static bool vaapi_functions_initialized = PostSandboxInitialization();
if (!vaapi_functions_initialized) {
@@ -360,21 +396,52 @@ bool VaapiWrapper::AreAttribsSupported(
return true;
}
-bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) {
- if (va_profile == VAProfileNone) {
- DVLOG(1) << "Unsupported profile";
- return false;
+bool VaapiWrapper::GetVaCodecMaxResolution(VAConfigID config_id,
+ gfx::Size* resolution) {
+ base::AutoLock auto_lock(va_lock_);
+ unsigned int num_attribs;
+ VAStatus va_res;
Pawel Osciak 2015/03/02 11:00:20 Please define each variable just before use.
henryhsu 2015/03/03 10:48:01 Done.
+
+ va_res = vaQuerySurfaceAttributes(
Pawel Osciak 2015/03/02 11:00:20 Please add a comment why we are calling this twic
henryhsu 2015/03/03 10:48:02 Done.
+ va_display_, config_id, NULL, &num_attribs);
+ VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false);
+
+ std::vector<VASurfaceAttrib> attrib_list(
Pawel Osciak 2015/03/02 11:00:20 Probably better to check if num_attribs != 0?
henryhsu 2015/03/03 10:48:01 Done.
+ base::checked_cast<size_t>(num_attribs));
+
+ va_res = vaQuerySurfaceAttributes(
+ va_display_, config_id, &attrib_list[0], &num_attribs);
+ VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false);
+
+ resolution->SetSize(0, 0);
+ for (size_t i = 0; i < num_attribs; i++) {
+ switch (attrib_list[i].type) {
wuchengli 2015/03/02 07:10:12 nit: using if clause can have less code. Up to you
henryhsu 2015/03/03 10:48:01 Done.
+ case VASurfaceAttribMaxWidth:
+ resolution->set_width(attrib_list[i].value.value.i);
+ break;
+ case VASurfaceAttribMaxHeight:
+ resolution->set_height(attrib_list[i].value.value.i);
+ break;
+ default:
+ break;
+ }
}
- VAEntrypoint entrypoint =
- (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
- if (!IsEntrypointSupported(va_profile, entrypoint))
+ if (!resolution->height() || !resolution->width()) {
kcwu 2015/03/02 14:02:18 resolution->IsEmpty()
henryhsu 2015/03/03 10:48:01 Done.
+ LOG(ERROR) << "Codec resolution cannot be zero.";
wuchengli 2015/03/02 07:10:12 also print resolution->ToString().
henryhsu 2015/03/03 10:48:01 Done.
return false;
- std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode);
- if (!AreAttribsSupported(va_profile, entrypoint, required_attribs))
+ }
+ return true;
+}
+
+bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) {
+ if (!profile_info_.Get().IsProfileSupported(mode, va_profile))
return false;
TryToSetVADisplayAttributeToLocalGPU();
+ VAEntrypoint entrypoint =
+ (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
+ std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode);
base::AutoLock auto_lock(va_lock_);
VAStatus va_res = vaCreateConfig(va_display_,
va_profile,
@@ -959,4 +1026,33 @@ bool VaapiWrapper::PostSandboxInitialization() {
return InitializeStubs(paths);
}
+VaapiWrapper::LazyProfileInfo::LazyProfileInfo() {
+ std::vector<VaapiWrapper::ProfileInfo> all_profile_info =
+ VaapiWrapper::InitSupportedProfileInfos();
+
+ for (size_t i = 0; i < all_profile_info.size(); ++i) {
kcwu 2015/03/02 14:02:18 how about for (const auto& info : all_profile_info
henryhsu 2015/03/03 10:48:02 Done.
+ supported_profiles_[all_profile_info[i].mode].push_back(
+ all_profile_info[i]);
+ }
+}
+
+VaapiWrapper::LazyProfileInfo::~LazyProfileInfo() {
+}
+
+std::vector<VaapiWrapper::ProfileInfo>
+VaapiWrapper::LazyProfileInfo::GetSupportedProfileInfos(
Pawel Osciak 2015/03/02 11:00:20 GetSupportedProfileInfosForCodecMode
henryhsu 2015/03/03 10:48:01 Done.
+ VaapiWrapper::CodecMode mode) {
+ CHECK(mode < VaapiWrapper::kCodecModeMax);
wuchengli 2015/03/02 07:10:12 Use DCHECK. See http://www.chromium.org/developers
Pawel Osciak 2015/03/02 11:00:20 I'd prefer if. Also, better to compare against sup
henryhsu 2015/03/03 10:48:01 supported_profiles_ is an array instead of class o
henryhsu 2015/03/03 10:48:02 Done.
+ return supported_profiles_[mode];
+}
+
+bool VaapiWrapper::LazyProfileInfo::IsProfileSupported(
+ VaapiWrapper::CodecMode mode, VAProfile va_profile) {
+ for (size_t i = 0; i < supported_profiles_[mode].size(); ++i) {
Pawel Osciak 2015/03/02 11:00:20 for (const auto& profile : supported_profiles_[mod
henryhsu 2015/03/03 10:48:02 Done.
+ if (supported_profiles_[mode][i].va_profile == va_profile)
+ return true;
+ }
+ return false;
+}
+
} // namespace content
« content/common/gpu/media/vaapi_wrapper.h ('K') | « content/common/gpu/media/vaapi_wrapper.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698