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

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: add comments 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..13f5854a7d7c8232a3ed17bc9a133663c7ebff49 100644
--- a/content/common/gpu/media/vaapi_wrapper.cc
+++ b/content/common/gpu/media/vaapi_wrapper.cc
@@ -8,12 +8,14 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/command_line.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/sys_info.h"
// Auto-generated for dlopen libva libraries
#include "content/common/gpu/media/va_stubs.h"
#include "content/common/gpu/media/vaapi_picture.h"
+#include "content/public/common/content_switches.h"
#include "third_party/libyuv/include/libyuv.h"
#include "ui/gl/gl_bindings.h"
#if defined(USE_X11)
@@ -56,6 +58,13 @@ using content_common_gpu_media::StubPathMap;
namespace content {
+// Maximum framerate of encoded profile. This value is an arbitary limit
+// and not taken from HW documentation.
+const int kMaxEncoderFramerate = 30;
+
+base::LazyInstance<VaapiWrapper::LazyProfileInfos>
+ VaapiWrapper::profile_infos_ = LAZY_INSTANCE_INITIALIZER;
+
// Config attributes common for both encode and decode.
static const VAConfigAttrib kCommonVAConfigAttribs[] = {
{VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420},
@@ -98,41 +107,6 @@ 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;
- for (size_t i = 0; i < arraysize(kProfileMap); i++) {
- if (kProfileMap[i].profile == profile) {
- va_profile = kProfileMap[i].va_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;
-}
-
VASurface::VASurface(VASurfaceID va_surface_id,
const gfx::Size& size,
const ReleaseCB& release_cb)
@@ -162,6 +136,7 @@ VaapiWrapper::~VaapiWrapper() {
Deinitialize();
}
+// static
scoped_ptr<VaapiWrapper> VaapiWrapper::Create(
CodecMode mode,
VAProfile va_profile,
@@ -170,12 +145,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;
Pawel Osciak 2015/03/08 00:58:24 Initialize() may fail for other reasons too. Perha
henryhsu 2015/03/09 03:56:52 Done.
return nullptr;
+ }
return vaapi_wrapper.Pass();
}
+// static
scoped_ptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec(
CodecMode mode,
media::VideoCodecProfile profile,
@@ -185,42 +164,50 @@ 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))
+ VAProfile va_profile = ProfileToVAProfile(profile, mode);
+ if (!vaapi_wrapper->Initialize(mode, va_profile)) {
+ DVLOG(1) << "Initialize failed. Profile: " << profile;
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;
- }
-
- 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<media::VideoEncodeAccelerator::SupportedProfile> profiles;
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ if (cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode))
+ return profiles;
+
+ std::vector<ProfileInfo> encode_profile_infos =
+ profile_infos_.Get().GetSupportedProfileInfosForCodecMode(kEncode);
+
+ for (size_t i = 0; i < arraysize(kProfileMap); ++i) {
+ VAProfile va_profile = ProfileToVAProfile(kProfileMap[i].profile, kEncode);
+ if (va_profile == VAProfileNone)
+ continue;
+ for (const auto& profile_info : encode_profile_infos) {
+ if (profile_info.va_profile == va_profile) {
+ media::VideoEncodeAccelerator::SupportedProfile profile;
+ profile.profile = kProfileMap[i].profile;
+ profile.max_resolution = profile_info.max_resolution;
+ profile.max_framerate_numerator = kMaxEncoderFramerate;
+ profile.max_framerate_denominator = 1;
+ profiles.push_back(profile);
+ }
Pawel Osciak 2015/03/08 00:58:24 Could we break here?
henryhsu 2015/03/09 03:56:52 Done.
}
}
- return supported_profiles;
+ return profiles;
+}
+
+// static
+std::vector<VaapiWrapper::ProfileInfo>
+VaapiWrapper::GetSupportedProfileInfosForCodecMode(CodecMode mode) {
+ scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper());
+ if (!vaapi_wrapper->VaInitialize(base::Bind(&base::DoNothing)))
+ return std::vector<ProfileInfo>();
+ return vaapi_wrapper->GetSupportedProfileInfosForCodecModeInternal(mode);
}
void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
@@ -236,6 +223,70 @@ void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default.";
}
+// static
+VAProfile VaapiWrapper::ProfileToVAProfile(
+ media::VideoCodecProfile profile, CodecMode mode) {
+ VAProfile va_profile = VAProfileNone;
+ for (size_t i = 0; i < arraysize(kProfileMap); ++i) {
+ if (kProfileMap[i].profile == profile) {
+ va_profile = kProfileMap[i].va_profile;
+ break;
+ }
+ }
+ if (!profile_infos_.Get().IsProfileSupported(mode, va_profile) &&
+ 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 (profile_infos_.Get().IsProfileSupported(
+ mode, VAProfileH264ConstrainedBaseline)) {
+ va_profile = VAProfileH264ConstrainedBaseline;
+ DVLOG(1) << "Fall back to constrained baseline profile.";
+ }
+ }
+ return va_profile;
+}
+
+std::vector<VaapiWrapper::ProfileInfo>
+VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) {
+ std::vector<ProfileInfo> supported_profile_infos;
+ std::vector<VAProfile> va_profiles;
+ if (!GetSupportedVaProfiles(&va_profiles))
+ return supported_profile_infos;
+
+ std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode);
+ VAEntrypoint entrypoint =
+ (mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD);
+
+ base::AutoLock auto_lock(va_lock_);
+ for (const auto& va_profile : va_profiles) {
+ if (!IsEntrypointSupported(va_profile, entrypoint))
+ continue;
+ if (!AreAttribsSupported(va_profile, entrypoint, required_attribs))
+ continue;
+ VAConfigID config_id;
+ VAStatus va_res = vaCreateConfig(
+ va_display_,
+ va_profile,
+ entrypoint,
+ &required_attribs[0],
+ required_attribs.size(),
+ &config_id);
+ if (va_res != VA_STATUS_SUCCESS) {
+ LOG_VA_ERROR_AND_REPORT(va_res, "vaCreateConfig failed");
+ continue;
+ }
+ ProfileInfo profile_info;
+ if (!GetMaxResolutionForVAConfigID(config_id, &profile_info.max_resolution))
Pawel Osciak 2015/03/08 00:58:24 I think we should LOG(ERROR) here, failure here ma
henryhsu 2015/03/09 03:56:52 Done.
+ continue;
+ profile_info.va_profile = va_profile;
+ supported_profile_infos.push_back(profile_info);
+ }
+ return supported_profile_infos;
+}
+
bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) {
static bool vaapi_functions_initialized = PostSandboxInitialization();
if (!vaapi_functions_initialized) {
@@ -306,7 +357,7 @@ bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) {
bool VaapiWrapper::IsEntrypointSupported(VAProfile va_profile,
VAEntrypoint entrypoint) {
- base::AutoLock auto_lock(va_lock_);
+ va_lock_.AssertAcquired();
// Query the driver for supported entrypoints.
int max_entrypoints = vaMaxNumEntrypoints(va_display_);
std::vector<VAEntrypoint> supported_entrypoints(
@@ -338,7 +389,7 @@ bool VaapiWrapper::AreAttribsSupported(
VAProfile va_profile,
VAEntrypoint entrypoint,
const std::vector<VAConfigAttrib>& required_attribs) {
- base::AutoLock auto_lock(va_lock_);
+ va_lock_.AssertAcquired();
// Query the driver for required attributes.
std::vector<VAConfigAttrib> attribs = required_attribs;
for (size_t i = 0; i < required_attribs.size(); ++i)
@@ -360,21 +411,52 @@ bool VaapiWrapper::AreAttribsSupported(
return true;
}
-bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) {
- if (va_profile == VAProfileNone) {
- DVLOG(1) << "Unsupported profile";
+bool VaapiWrapper::GetMaxResolutionForVAConfigID(VAConfigID va_config_id,
+ gfx::Size* resolution) {
+ va_lock_.AssertAcquired();
+ unsigned int num_attribs;
+
+ // Calls vaQuerySurfaceAttributes twice. The first time is to get the number
+ // of attributes to prepare the space and the second time is to get all
+ // attributes.
+ VAStatus va_res;
+ va_res = vaQuerySurfaceAttributes(
+ va_display_, va_config_id, NULL, &num_attribs);
Pawel Osciak 2015/03/08 00:58:24 s/NULL/nullptr/
henryhsu 2015/03/09 03:56:52 Done.
+ VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false);
+ if (!num_attribs)
return false;
+
+ std::vector<VASurfaceAttrib> attrib_list(
+ base::checked_cast<size_t>(num_attribs));
+
+ va_res = vaQuerySurfaceAttributes(
+ va_display_, va_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++) {
Pawel Osciak 2015/03/08 00:58:24 for (const auto& attrib : attrib_list)
henryhsu 2015/03/09 03:56:52 Done.
+ if (attrib_list[i].type == VASurfaceAttribMaxWidth)
+ resolution->set_width(attrib_list[i].value.value.i);
+ else if (attrib_list[i].type == VASurfaceAttribMaxHeight)
+ resolution->set_height(attrib_list[i].value.value.i);
}
- VAEntrypoint entrypoint =
- (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
- if (!IsEntrypointSupported(va_profile, entrypoint))
+ if (resolution->IsEmpty()) {
+ LOG(ERROR) << "Codec resolution " << resolution->ToString()
+ << " cannot be zero.";
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_infos_.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,
@@ -573,13 +655,13 @@ bool VaapiWrapper::SubmitVAEncMiscParamBuffer(
void VaapiWrapper::DestroyPendingBuffers() {
base::AutoLock auto_lock(va_lock_);
- for (size_t i = 0; i < pending_va_bufs_.size(); ++i) {
- VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_bufs_[i]);
+ for (const auto& pending_va_buf : pending_va_bufs_) {
+ VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_buf);
VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
}
- for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) {
- VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_bufs_[i]);
+ for (const auto& pending_slice_buf : pending_slice_bufs_) {
+ VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_buf);
VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
}
@@ -959,4 +1041,30 @@ bool VaapiWrapper::PostSandboxInitialization() {
return InitializeStubs(paths);
}
+VaapiWrapper::LazyProfileInfos::LazyProfileInfos() {
+ for (size_t i = 0; i < kCodecModeMax; ++i) {
Pawel Osciak 2015/03/08 00:58:24 Ok, but let's at least do static_assert(arraysize(
henryhsu 2015/03/09 03:56:52 Done.
+ supported_profiles_[i] =
+ VaapiWrapper::GetSupportedProfileInfosForCodecMode(
+ static_cast<CodecMode>(i));
+ }
+}
+
+VaapiWrapper::LazyProfileInfos::~LazyProfileInfos() {
+}
+
+std::vector<VaapiWrapper::ProfileInfo>
+VaapiWrapper::LazyProfileInfos::GetSupportedProfileInfosForCodecMode(
+ CodecMode mode) {
+ return supported_profiles_[mode];
+}
+
+bool VaapiWrapper::LazyProfileInfos::IsProfileSupported(
+ CodecMode mode, VAProfile va_profile) {
+ for (const auto& profile : supported_profiles_[mode]) {
+ if (profile.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