Chromium Code Reviews| 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 63450b4a58001dba70505640f3b9197e7f75c896..2ea163c8b50417e022be6b12be8d0f77baea306f 100644 |
| --- a/content/common/gpu/media/vaapi_wrapper.cc |
| +++ b/content/common/gpu/media/vaapi_wrapper.cc |
| @@ -56,6 +56,11 @@ using content_common_gpu_media::StubPathMap; |
| namespace content { |
| +bool VaapiWrapper::is_initialize_profile_; |
| +VaapiWrapper::ProfileConfig |
| + VaapiWrapper::supported_profiles_[media::VIDEO_CODEC_PROFILE_MAX * 2] = |
|
kcwu
2015/02/02 10:11:01
MAX*2+1
henryhsu
2015/02/13 04:01:03
Not used anymore
|
| + {{media::VIDEO_CODEC_PROFILE_UNKNOWN}}; |
|
kcwu
2015/02/02 10:11:01
add comment that UNKNOWN is guard.
henryhsu
2015/02/13 04:01:03
Not used anymore
|
| + |
| // Config attributes common for both encode and decode. |
| static const VAConfigAttrib kCommonVAConfigAttribs[] = { |
| {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, |
| @@ -99,10 +104,7 @@ static std::vector<VAConfigAttrib> GetRequiredAttribs( |
| } |
| // Maps Profile enum values to VaProfile values. |
| -static VAProfile ProfileToVAProfile( |
| - media::VideoCodecProfile profile, |
| - const std::vector<VAProfile>& supported_profiles) { |
| - |
| +static VAProfile ProfileToVAProfile(media::VideoCodecProfile profile) { |
| VAProfile va_profile = VAProfileNone; |
| for (size_t i = 0; i < arraysize(kProfileMap); i++) { |
| if (kProfileMap[i].profile == profile) { |
| @@ -110,23 +112,33 @@ static VAProfile ProfileToVAProfile( |
| break; |
| } |
| } |
| + return va_profile; |
| +} |
| +// checks VaProfile is supported. |
| +static VAProfile GetSupportedVaProfile( |
| + VAProfile va_profile, |
| + const std::vector<VAProfile>& supported_profiles) { |
| 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."; |
| + if (!supported) { |
| + if (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."; |
| + } |
| + } else { |
| + va_profile = VAProfileNone; |
| } |
| } |
| @@ -162,43 +174,61 @@ VaapiWrapper::~VaapiWrapper() { |
| Deinitialize(); |
| } |
| +// static |
| +scoped_ptr<VaapiWrapper> VaapiWrapper::CreateInstance( |
| + const base::Closure& report_error_to_uma_cb) { |
| + scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
| + if (!vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) |
| + vaapi_wrapper.reset(); |
| + else |
| + vaapi_wrapper->InitializeSupportedProfiles(); |
| + return vaapi_wrapper.Pass(); |
| +} |
| + |
| +// static |
| scoped_ptr<VaapiWrapper> VaapiWrapper::Create( |
|
kcwu
2015/02/02 10:11:01
you need to rebase since I modified these function
henryhsu
2015/02/13 04:01:03
Done.
|
| CodecMode mode, |
| media::VideoCodecProfile profile, |
| const base::Closure& report_error_to_uma_cb) { |
| - scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
| + scoped_ptr<VaapiWrapper> vaapi_wrapper = |
| + CreateInstance(report_error_to_uma_cb); |
| - if (!vaapi_wrapper->Initialize(mode, profile, report_error_to_uma_cb)) |
| + if (vaapi_wrapper && |
| + !vaapi_wrapper->Initialize(mode, profile)) |
| vaapi_wrapper.reset(); |
| return vaapi_wrapper.Pass(); |
| } |
| -std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles( |
| - const base::Closure& report_error_to_uma_cb) { |
| +// static |
| +std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedProfiles( |
| + CodecMode mode) { |
| std::vector<media::VideoCodecProfile> supported_profiles; |
| - |
| - scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper()); |
| - if (!wrapper->VaInitialize(report_error_to_uma_cb)) { |
| + if (!CreateInstance(base::Bind(&base::DoNothing))) |
| return supported_profiles; |
| + for (size_t i = 0; |
| + supported_profiles_[i].profile != media::VIDEO_CODEC_PROFILE_UNKNOWN; |
| + ++i) { |
| + if (supported_profiles_[i].mode == mode) |
| + supported_profiles.push_back(supported_profiles_[i].profile); |
| } |
| + 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 |
| +gfx::Size VaapiWrapper::GetCodecMaxResolution( |
| + media::VideoCodecProfile profile, |
| + CodecMode mode) { |
| + if (!CreateInstance(base::Bind(&base::DoNothing))) |
| + return gfx::Size(0, 0); |
| + for (size_t i = 0; |
| + supported_profiles_[i].profile != media::VIDEO_CODEC_PROFILE_UNKNOWN; |
| + ++i) { |
| + if (supported_profiles_[i].profile == profile && |
| + supported_profiles_[i].mode == mode) |
| + return supported_profiles_[i].max_resolution; |
| } |
| - return supported_profiles; |
| + return gfx::Size(0, 0); |
| } |
| void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
| @@ -214,6 +244,48 @@ void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
| DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
| } |
| +void VaapiWrapper::InitializeSupportedProfiles() { |
| + if (is_initialize_profile_) |
|
wuchengli
2015/02/03 03:17:33
Originally this class is thread-safe. You need |va
henryhsu
2015/02/13 04:01:03
Done.
|
| + return; |
| + std::vector<VAProfile> va_profiles; |
| + if (!GetSupportedVaProfiles(&va_profiles)) |
| + return; |
| + |
| + size_t num_profiles = 0; |
| + std::vector<CodecMode> modes({kDecode, kEncode}); |
| + for (size_t i = 0; i < arraysize(kProfileMap); i++) { |
|
kcwu
2015/02/02 10:11:01
DCHECK_LT(arraysize(kProfileMap) * modes.size(), a
henryhsu
2015/02/13 04:01:03
Not used anymore
|
| + VAProfile va_profile = kProfileMap[i].va_profile; |
| + for (size_t j = 0; j < modes.size(); j++) { |
| + std::vector<VAConfigAttrib> required_attribs = |
| + GetRequiredAttribs(modes[j]); |
| + VAEntrypoint entrypoint = |
| + (modes[j] == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD); |
| + if (GetSupportedVaProfile(va_profile, va_profiles) != VAProfileNone && |
| + IsEntrypointSupported(va_profile, entrypoint) && |
| + AreAttribsSupported(va_profile, entrypoint, required_attribs)) { |
| + supported_profiles_[num_profiles].profile = kProfileMap[i].profile; |
| + supported_profiles_[num_profiles].mode = modes[j]; |
| + 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) { |
| + GetVaCodecMaxResolution(config_id, |
|
kcwu
2015/02/02 10:11:02
didn't check return value?
henryhsu
2015/02/13 04:01:03
Done.
|
| + &supported_profiles_[num_profiles].max_resolution); |
| + num_profiles++; |
| + } |
| + } |
| + } |
| + } |
| + supported_profiles_[num_profiles].profile = |
| + media::VIDEO_CODEC_PROFILE_UNKNOWN; |
| + is_initialize_profile_ = true; |
| +} |
| + |
| bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) { |
| static bool vaapi_functions_initialized = PostSandboxInitialization(); |
| if (!vaapi_functions_initialized) { |
| @@ -338,29 +410,61 @@ bool VaapiWrapper::AreAttribsSupported( |
| return true; |
| } |
| +bool VaapiWrapper::GetVaCodecMaxResolution(VAConfigID config_id, |
| + gfx::Size* resolution) { |
| + base::AutoLock auto_lock(va_lock_); |
| + unsigned int num_attribs; |
| + VAStatus va_res; |
| + |
| + va_res = vaQuerySurfaceAttributes( |
| + va_display_, config_id, NULL, &num_attribs); |
| + VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false); |
| + |
| + std::vector<VASurfaceAttrib> attrib_list( |
| + 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) { |
| + 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; |
| + } |
| + } |
| + return true; |
|
kcwu
2015/02/02 10:11:02
Is it guaranteed that there are always VaSurfaceAt
henryhsu
2015/02/02 10:42:24
No. If attributes don't include MaxWidth and MaxHe
|
| +} |
| + |
| bool VaapiWrapper::Initialize(CodecMode mode, |
| - media::VideoCodecProfile profile, |
| - const base::Closure& report_error_to_uma_cb) { |
| - if (!VaInitialize(report_error_to_uma_cb)) |
| - return false; |
| - std::vector<VAProfile> supported_va_profiles; |
| - if (!GetSupportedVaProfiles(&supported_va_profiles)) |
| + media::VideoCodecProfile profile) { |
| + std::vector<media::VideoCodecProfile> supported_profiles = |
| + GetSupportedProfiles(mode); |
| + if (std::find(supported_profiles.begin(), |
| + supported_profiles.end(), |
| + profile) == supported_profiles.end()) { |
| + DVLOG(1) << "Unsupported profile"; |
| return false; |
| - VAProfile va_profile = ProfileToVAProfile(profile, supported_va_profiles); |
| + } |
| + |
| + VAProfile va_profile = ProfileToVAProfile(profile); |
| 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(); |
| + 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, |