Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/common/gpu/media/vaapi_wrapper.h" | 5 #include "content/common/gpu/media/vaapi_wrapper.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 11 #include "base/command_line.h" | |
| 11 #include "base/logging.h" | 12 #include "base/logging.h" |
| 12 #include "base/numerics/safe_conversions.h" | 13 #include "base/numerics/safe_conversions.h" |
| 13 #include "base/sys_info.h" | 14 #include "base/sys_info.h" |
| 14 // Auto-generated for dlopen libva libraries | 15 // Auto-generated for dlopen libva libraries |
| 15 #include "content/common/gpu/media/va_stubs.h" | 16 #include "content/common/gpu/media/va_stubs.h" |
| 16 #include "content/common/gpu/media/vaapi_picture.h" | 17 #include "content/common/gpu/media/vaapi_picture.h" |
| 18 #include "content/public/common/content_switches.h" | |
| 17 #include "third_party/libyuv/include/libyuv.h" | 19 #include "third_party/libyuv/include/libyuv.h" |
| 18 #include "ui/gl/gl_bindings.h" | 20 #include "ui/gl/gl_bindings.h" |
| 19 #if defined(USE_X11) | 21 #if defined(USE_X11) |
| 20 #include "ui/gfx/x/x11_types.h" | 22 #include "ui/gfx/x/x11_types.h" |
| 21 #elif defined(USE_OZONE) | 23 #elif defined(USE_OZONE) |
| 22 #include "third_party/libva/va/drm/va_drm.h" | 24 #include "third_party/libva/va/drm/va_drm.h" |
| 23 #include "ui/ozone/public/ozone_platform.h" | 25 #include "ui/ozone/public/ozone_platform.h" |
| 24 #include "ui/ozone/public/surface_factory_ozone.h" | 26 #include "ui/ozone/public/surface_factory_ozone.h" |
| 25 #endif // USE_X11 | 27 #endif // USE_X11 |
| 26 | 28 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 49 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ | 51 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ |
| 50 do { \ | 52 do { \ |
| 51 if ((va_error) != VA_STATUS_SUCCESS) { \ | 53 if ((va_error) != VA_STATUS_SUCCESS) { \ |
| 52 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ | 54 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ |
| 53 return (ret); \ | 55 return (ret); \ |
| 54 } \ | 56 } \ |
| 55 } while (0) | 57 } while (0) |
| 56 | 58 |
| 57 namespace content { | 59 namespace content { |
| 58 | 60 |
| 61 // Maximum framerate of encoded profile. This value is an arbitary limit | |
| 62 // and not taken from HW documentation. | |
| 63 const int kMaxEncoderFramerate = 30; | |
| 64 | |
| 65 base::LazyInstance<VaapiWrapper::LazyProfileInfos> | |
| 66 VaapiWrapper::profile_infos_ = LAZY_INSTANCE_INITIALIZER; | |
| 67 | |
| 59 // Config attributes common for both encode and decode. | 68 // Config attributes common for both encode and decode. |
| 60 static const VAConfigAttrib kCommonVAConfigAttribs[] = { | 69 static const VAConfigAttrib kCommonVAConfigAttribs[] = { |
| 61 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, | 70 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, |
| 62 }; | 71 }; |
| 63 | 72 |
| 64 // Attributes required for encode. | 73 // Attributes required for encode. |
| 65 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { | 74 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { |
| 66 {VAConfigAttribRateControl, VA_RC_CBR}, | 75 {VAConfigAttribRateControl, VA_RC_CBR}, |
| 67 {VAConfigAttribEncPackedHeaders, | 76 {VAConfigAttribEncPackedHeaders, |
| 68 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, | 77 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 91 kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs)); | 100 kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs)); |
| 92 if (mode == VaapiWrapper::kEncode) { | 101 if (mode == VaapiWrapper::kEncode) { |
| 93 required_attribs.insert( | 102 required_attribs.insert( |
| 94 required_attribs.end(), | 103 required_attribs.end(), |
| 95 kEncodeVAConfigAttribs, | 104 kEncodeVAConfigAttribs, |
| 96 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); | 105 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); |
| 97 } | 106 } |
| 98 return required_attribs; | 107 return required_attribs; |
| 99 } | 108 } |
| 100 | 109 |
| 101 // Maps Profile enum values to VaProfile values. | |
| 102 static VAProfile ProfileToVAProfile( | |
| 103 media::VideoCodecProfile profile, | |
| 104 const std::vector<VAProfile>& supported_profiles) { | |
| 105 | |
| 106 VAProfile va_profile = VAProfileNone; | |
| 107 for (size_t i = 0; i < arraysize(kProfileMap); i++) { | |
| 108 if (kProfileMap[i].profile == profile) { | |
| 109 va_profile = kProfileMap[i].va_profile; | |
| 110 break; | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 bool supported = std::find(supported_profiles.begin(), | |
| 115 supported_profiles.end(), | |
| 116 va_profile) != supported_profiles.end(); | |
| 117 | |
| 118 if (!supported && va_profile == VAProfileH264Baseline) { | |
| 119 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips | |
| 120 // the information whether the profile is constrained or not, so we have no | |
| 121 // way to know here. Try for baseline first, but if it is not supported, | |
| 122 // try constrained baseline and hope this is what it actually is | |
| 123 // (which in practice is true for a great majority of cases). | |
| 124 if (std::find(supported_profiles.begin(), | |
| 125 supported_profiles.end(), | |
| 126 VAProfileH264ConstrainedBaseline) != | |
| 127 supported_profiles.end()) { | |
| 128 va_profile = VAProfileH264ConstrainedBaseline; | |
| 129 DVLOG(1) << "Falling back to constrained baseline profile."; | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 return va_profile; | |
| 134 } | |
| 135 | |
| 136 VASurface::VASurface(VASurfaceID va_surface_id, | 110 VASurface::VASurface(VASurfaceID va_surface_id, |
| 137 const gfx::Size& size, | 111 const gfx::Size& size, |
| 138 const ReleaseCB& release_cb) | 112 const ReleaseCB& release_cb) |
| 139 : va_surface_id_(va_surface_id), size_(size), release_cb_(release_cb) { | 113 : va_surface_id_(va_surface_id), size_(size), release_cb_(release_cb) { |
| 140 DCHECK(!release_cb_.is_null()); | 114 DCHECK(!release_cb_.is_null()); |
| 141 } | 115 } |
| 142 | 116 |
| 143 VASurface::~VASurface() { | 117 VASurface::~VASurface() { |
| 144 release_cb_.Run(va_surface_id_); | 118 release_cb_.Run(va_surface_id_); |
| 145 } | 119 } |
| 146 | 120 |
| 147 VaapiWrapper::VaapiWrapper() | 121 VaapiWrapper::VaapiWrapper() |
| 148 : va_display_(NULL), | 122 : va_display_(NULL), |
| 149 va_config_id_(VA_INVALID_ID), | 123 va_config_id_(VA_INVALID_ID), |
| 150 va_context_id_(VA_INVALID_ID), | 124 va_context_id_(VA_INVALID_ID), |
| 151 va_initialized_(false), | 125 va_initialized_(false), |
| 152 va_vpp_config_id_(VA_INVALID_ID), | 126 va_vpp_config_id_(VA_INVALID_ID), |
| 153 va_vpp_context_id_(VA_INVALID_ID), | 127 va_vpp_context_id_(VA_INVALID_ID), |
| 154 va_vpp_buffer_id_(VA_INVALID_ID) { | 128 va_vpp_buffer_id_(VA_INVALID_ID) { |
| 155 } | 129 } |
| 156 | 130 |
| 157 VaapiWrapper::~VaapiWrapper() { | 131 VaapiWrapper::~VaapiWrapper() { |
| 158 DestroyPendingBuffers(); | 132 DestroyPendingBuffers(); |
| 159 DestroyCodedBuffers(); | 133 DestroyCodedBuffers(); |
| 160 DestroySurfaces(); | 134 DestroySurfaces(); |
| 161 DeinitializeVpp(); | 135 DeinitializeVpp(); |
| 162 Deinitialize(); | 136 Deinitialize(); |
| 163 } | 137 } |
| 164 | 138 |
| 139 // static | |
| 165 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( | 140 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( |
| 166 CodecMode mode, | 141 CodecMode mode, |
| 167 VAProfile va_profile, | 142 VAProfile va_profile, |
| 168 const base::Closure& report_error_to_uma_cb) { | 143 const base::Closure& report_error_to_uma_cb) { |
| 169 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 144 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
| 170 | 145 |
| 171 if (!vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) | 146 if (!vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) |
| 172 return nullptr; | 147 return nullptr; |
| 148 | |
| 173 if (!vaapi_wrapper->Initialize(mode, va_profile)) | 149 if (!vaapi_wrapper->Initialize(mode, va_profile)) |
| 174 return nullptr; | 150 return nullptr; |
| 175 | 151 |
| 176 return vaapi_wrapper.Pass(); | 152 return vaapi_wrapper.Pass(); |
| 177 } | 153 } |
| 178 | 154 |
| 155 // static | |
| 179 scoped_ptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec( | 156 scoped_ptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec( |
| 180 CodecMode mode, | 157 CodecMode mode, |
| 181 media::VideoCodecProfile profile, | 158 media::VideoCodecProfile profile, |
| 182 const base::Closure& report_error_to_uma_cb) { | 159 const base::Closure& report_error_to_uma_cb) { |
| 183 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 160 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
| 184 | 161 |
| 185 if (!vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) | 162 if (!vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) |
| 186 return nullptr; | 163 return nullptr; |
| 187 | 164 |
| 188 std::vector<VAProfile> supported_va_profiles; | 165 VAProfile va_profile = ProfileToVAProfile(profile, mode); |
| 189 if (!vaapi_wrapper->GetSupportedVaProfiles(&supported_va_profiles)) | |
| 190 return nullptr; | |
| 191 | |
| 192 VAProfile va_profile = ProfileToVAProfile(profile, supported_va_profiles); | |
| 193 if (!vaapi_wrapper->Initialize(mode, va_profile)) | 166 if (!vaapi_wrapper->Initialize(mode, va_profile)) |
| 194 return nullptr; | 167 return nullptr; |
| 195 | 168 |
| 196 return vaapi_wrapper.Pass(); | 169 return vaapi_wrapper.Pass(); |
| 197 } | 170 } |
| 198 | 171 |
| 199 std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles( | 172 // static |
| 200 const base::Closure& report_error_to_uma_cb) { | 173 std::vector<media::VideoEncodeAccelerator::SupportedProfile> |
| 201 std::vector<media::VideoCodecProfile> supported_profiles; | 174 VaapiWrapper::GetSupportedEncodeProfiles() { |
| 175 std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles; | |
| 176 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | |
| 177 if (cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode)) | |
| 178 return profiles; | |
| 202 | 179 |
| 203 scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper()); | 180 std::vector<ProfileInfo> encode_profile_infos = |
| 204 if (!wrapper->VaInitialize(report_error_to_uma_cb)) { | 181 profile_infos_.Get().GetSupportedProfileInfosForCodecMode(kEncode); |
| 205 return supported_profiles; | |
| 206 } | |
| 207 | 182 |
| 208 std::vector<VAProfile> va_profiles; | 183 for (size_t i = 0; i < arraysize(kProfileMap); ++i) { |
| 209 if (!wrapper->GetSupportedVaProfiles(&va_profiles)) | 184 VAProfile va_profile = ProfileToVAProfile(kProfileMap[i].profile, kEncode); |
| 210 return supported_profiles; | 185 if (va_profile == VAProfileNone) |
| 211 | 186 continue; |
| 212 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode); | 187 for (const auto& profile_info : encode_profile_infos) { |
| 213 for (size_t i = 0; i < arraysize(kProfileMap); i++) { | 188 if (profile_info.va_profile == va_profile) { |
| 214 VAProfile va_profile = | 189 media::VideoEncodeAccelerator::SupportedProfile profile; |
| 215 ProfileToVAProfile(kProfileMap[i].profile, va_profiles); | 190 profile.profile = kProfileMap[i].profile; |
| 216 if (va_profile != VAProfileNone && | 191 profile.max_resolution = profile_info.max_resolution; |
| 217 wrapper->IsEntrypointSupported(va_profile, VAEntrypointEncSlice) && | 192 profile.max_framerate_numerator = kMaxEncoderFramerate; |
| 218 wrapper->AreAttribsSupported( | 193 profile.max_framerate_denominator = 1; |
| 219 va_profile, VAEntrypointEncSlice, required_attribs)) { | 194 profiles.push_back(profile); |
| 220 supported_profiles.push_back(kProfileMap[i].profile); | 195 break; |
| 196 } | |
| 221 } | 197 } |
| 222 } | 198 } |
| 223 return supported_profiles; | 199 return profiles; |
| 224 } | 200 } |
| 225 | 201 |
| 226 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { | 202 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
| 227 base::AutoLock auto_lock(va_lock_); | 203 base::AutoLock auto_lock(va_lock_); |
| 228 VADisplayAttribute item = {VADisplayAttribRenderMode, | 204 VADisplayAttribute item = {VADisplayAttribRenderMode, |
| 229 1, // At least support '_LOCAL_OVERLAY'. | 205 1, // At least support '_LOCAL_OVERLAY'. |
| 230 -1, // The maximum possible support 'ALL'. | 206 -1, // The maximum possible support 'ALL'. |
| 231 VA_RENDER_MODE_LOCAL_GPU, | 207 VA_RENDER_MODE_LOCAL_GPU, |
| 232 VA_DISPLAY_ATTRIB_SETTABLE}; | 208 VA_DISPLAY_ATTRIB_SETTABLE}; |
| 233 | 209 |
| 234 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 210 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
| 235 if (va_res != VA_STATUS_SUCCESS) | 211 if (va_res != VA_STATUS_SUCCESS) |
| 236 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 212 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
| 237 } | 213 } |
| 238 | 214 |
| 215 // static | |
| 216 VAProfile VaapiWrapper::ProfileToVAProfile( | |
| 217 media::VideoCodecProfile profile, CodecMode mode) { | |
| 218 VAProfile va_profile = VAProfileNone; | |
| 219 for (size_t i = 0; i < arraysize(kProfileMap); ++i) { | |
| 220 if (kProfileMap[i].profile == profile) { | |
| 221 va_profile = kProfileMap[i].va_profile; | |
| 222 break; | |
| 223 } | |
| 224 } | |
| 225 if (!profile_infos_.Get().IsProfileSupported(mode, va_profile) && | |
| 226 va_profile == VAProfileH264Baseline) { | |
| 227 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips | |
| 228 // the information whether the profile is constrained or not, so we have no | |
| 229 // way to know here. Try for baseline first, but if it is not supported, | |
| 230 // try constrained baseline and hope this is what it actually is | |
| 231 // (which in practice is true for a great majority of cases). | |
| 232 if (profile_infos_.Get().IsProfileSupported( | |
| 233 mode, VAProfileH264ConstrainedBaseline)) { | |
| 234 va_profile = VAProfileH264ConstrainedBaseline; | |
| 235 DVLOG(1) << "Fall back to constrained baseline profile."; | |
| 236 } | |
| 237 } | |
| 238 return va_profile; | |
| 239 } | |
| 240 | |
| 241 std::vector<VaapiWrapper::ProfileInfo> | |
| 242 VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) { | |
| 243 std::vector<ProfileInfo> supported_profile_infos; | |
| 244 std::vector<VAProfile> va_profiles; | |
| 245 if (!GetSupportedVaProfiles(&va_profiles)) | |
| 246 return supported_profile_infos; | |
| 247 | |
| 248 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | |
| 249 VAEntrypoint entrypoint = | |
| 250 (mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD); | |
| 251 | |
| 252 base::AutoLock auto_lock(va_lock_); | |
| 253 for (const auto& va_profile : va_profiles) { | |
| 254 if (!IsEntrypointSupported_Locked(va_profile, entrypoint)) | |
| 255 continue; | |
| 256 if (!AreAttribsSupported_Locked(va_profile, entrypoint, required_attribs)) | |
| 257 continue; | |
| 258 ProfileInfo profile_info; | |
| 259 if (!GetMaxResolution_Locked(va_profile, | |
| 260 entrypoint, | |
| 261 required_attribs, | |
| 262 &profile_info.max_resolution)) { | |
| 263 LOG(ERROR) << "GetMaxResolution failed by va_profile " << va_profile; | |
|
Pawel Osciak
2015/03/10 03:41:14
s/by/for/
Also please add entrypoint to the messag
henryhsu
2015/03/10 05:36:53
Done.
| |
| 264 continue; | |
| 265 } | |
| 266 profile_info.va_profile = va_profile; | |
| 267 supported_profile_infos.push_back(profile_info); | |
| 268 } | |
| 269 return supported_profile_infos; | |
| 270 } | |
| 271 | |
| 239 bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) { | 272 bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) { |
| 240 static bool vaapi_functions_initialized = PostSandboxInitialization(); | 273 static bool vaapi_functions_initialized = PostSandboxInitialization(); |
| 241 if (!vaapi_functions_initialized) { | 274 if (!vaapi_functions_initialized) { |
| 242 bool running_on_chromeos = false; | 275 bool running_on_chromeos = false; |
| 243 #if defined(OS_CHROMEOS) | 276 #if defined(OS_CHROMEOS) |
| 244 // When chrome runs on linux with chromeos=1, do not log error message | 277 // When chrome runs on linux with chromeos=1, do not log error message |
| 245 // without VAAPI libraries. | 278 // without VAAPI libraries. |
| 246 running_on_chromeos = base::SysInfo::IsRunningOnChromeOS(); | 279 running_on_chromeos = base::SysInfo::IsRunningOnChromeOS(); |
| 247 #endif | 280 #endif |
| 248 static const char kErrorMsg[] = "Failed to initialize VAAPI libs"; | 281 static const char kErrorMsg[] = "Failed to initialize VAAPI libs"; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { | 330 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { |
| 298 LOG(ERROR) << "vaQueryConfigProfiles returned: " << num_supported_profiles; | 331 LOG(ERROR) << "vaQueryConfigProfiles returned: " << num_supported_profiles; |
| 299 return false; | 332 return false; |
| 300 } | 333 } |
| 301 | 334 |
| 302 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); | 335 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); |
| 303 *profiles = supported_profiles; | 336 *profiles = supported_profiles; |
| 304 return true; | 337 return true; |
| 305 } | 338 } |
| 306 | 339 |
| 307 bool VaapiWrapper::IsEntrypointSupported(VAProfile va_profile, | 340 bool VaapiWrapper::IsEntrypointSupported_Locked(VAProfile va_profile, |
| 308 VAEntrypoint entrypoint) { | 341 VAEntrypoint entrypoint) { |
| 309 base::AutoLock auto_lock(va_lock_); | 342 va_lock_.AssertAcquired(); |
| 310 // Query the driver for supported entrypoints. | 343 // Query the driver for supported entrypoints. |
| 311 int max_entrypoints = vaMaxNumEntrypoints(va_display_); | 344 int max_entrypoints = vaMaxNumEntrypoints(va_display_); |
| 312 std::vector<VAEntrypoint> supported_entrypoints( | 345 std::vector<VAEntrypoint> supported_entrypoints( |
| 313 base::checked_cast<size_t>(max_entrypoints)); | 346 base::checked_cast<size_t>(max_entrypoints)); |
| 314 | 347 |
| 315 int num_supported_entrypoints; | 348 int num_supported_entrypoints; |
| 316 VAStatus va_res = vaQueryConfigEntrypoints(va_display_, | 349 VAStatus va_res = vaQueryConfigEntrypoints(va_display_, |
| 317 va_profile, | 350 va_profile, |
| 318 &supported_entrypoints[0], | 351 &supported_entrypoints[0], |
| 319 &num_supported_entrypoints); | 352 &num_supported_entrypoints); |
| 320 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); | 353 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); |
| 321 if (num_supported_entrypoints < 0 || | 354 if (num_supported_entrypoints < 0 || |
| 322 num_supported_entrypoints > max_entrypoints) { | 355 num_supported_entrypoints > max_entrypoints) { |
| 323 LOG(ERROR) << "vaQueryConfigEntrypoints returned: " | 356 LOG(ERROR) << "vaQueryConfigEntrypoints returned: " |
| 324 << num_supported_entrypoints; | 357 << num_supported_entrypoints; |
| 325 return false; | 358 return false; |
| 326 } | 359 } |
| 327 | 360 |
| 328 if (std::find(supported_entrypoints.begin(), | 361 if (std::find(supported_entrypoints.begin(), |
| 329 supported_entrypoints.end(), | 362 supported_entrypoints.end(), |
| 330 entrypoint) == supported_entrypoints.end()) { | 363 entrypoint) == supported_entrypoints.end()) { |
| 331 DVLOG(1) << "Unsupported entrypoint"; | 364 DVLOG(1) << "Unsupported entrypoint"; |
| 332 return false; | 365 return false; |
| 333 } | 366 } |
| 334 return true; | 367 return true; |
| 335 } | 368 } |
| 336 | 369 |
| 337 bool VaapiWrapper::AreAttribsSupported( | 370 bool VaapiWrapper::AreAttribsSupported_Locked( |
| 338 VAProfile va_profile, | 371 VAProfile va_profile, |
| 339 VAEntrypoint entrypoint, | 372 VAEntrypoint entrypoint, |
| 340 const std::vector<VAConfigAttrib>& required_attribs) { | 373 const std::vector<VAConfigAttrib>& required_attribs) { |
| 341 base::AutoLock auto_lock(va_lock_); | 374 va_lock_.AssertAcquired(); |
| 342 // Query the driver for required attributes. | 375 // Query the driver for required attributes. |
| 343 std::vector<VAConfigAttrib> attribs = required_attribs; | 376 std::vector<VAConfigAttrib> attribs = required_attribs; |
| 344 for (size_t i = 0; i < required_attribs.size(); ++i) | 377 for (size_t i = 0; i < required_attribs.size(); ++i) |
| 345 attribs[i].value = 0; | 378 attribs[i].value = 0; |
| 346 | 379 |
| 347 VAStatus va_res = vaGetConfigAttributes( | 380 VAStatus va_res = vaGetConfigAttributes( |
| 348 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); | 381 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); |
| 349 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); | 382 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); |
| 350 | 383 |
| 351 for (size_t i = 0; i < required_attribs.size(); ++i) { | 384 for (size_t i = 0; i < required_attribs.size(); ++i) { |
| 352 if (attribs[i].type != required_attribs[i].type || | 385 if (attribs[i].type != required_attribs[i].type || |
| 353 (attribs[i].value & required_attribs[i].value) != | 386 (attribs[i].value & required_attribs[i].value) != |
| 354 required_attribs[i].value) { | 387 required_attribs[i].value) { |
| 355 DVLOG(1) << "Unsupported value " << required_attribs[i].value | 388 DVLOG(1) << "Unsupported value " << required_attribs[i].value |
| 356 << " for attribute type " << required_attribs[i].type; | 389 << " for attribute type " << required_attribs[i].type; |
| 357 return false; | 390 return false; |
| 358 } | 391 } |
| 359 } | 392 } |
| 360 return true; | 393 return true; |
| 361 } | 394 } |
| 362 | 395 |
| 396 bool VaapiWrapper::GetMaxResolution_Locked( | |
| 397 VAProfile va_profile, | |
| 398 VAEntrypoint entrypoint, | |
| 399 std::vector<VAConfigAttrib>& required_attribs, | |
| 400 gfx::Size* resolution) { | |
| 401 va_lock_.AssertAcquired(); | |
| 402 VAConfigID va_config_id; | |
| 403 VAStatus va_res; | |
| 404 va_res = vaCreateConfig( | |
|
Pawel Osciak
2015/03/10 03:41:14
Nit: VAStatus va_res = ...
henryhsu
2015/03/10 05:36:52
Done.
| |
| 405 va_display_, | |
| 406 va_profile, | |
| 407 entrypoint, | |
| 408 &required_attribs[0], | |
| 409 required_attribs.size(), | |
| 410 &va_config_id); | |
| 411 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); | |
| 412 | |
| 413 // Calls vaQuerySurfaceAttributes twice. The first time is to get the number | |
| 414 // of attributes to prepare the space and the second time is to get all | |
| 415 // attributes. | |
| 416 unsigned int num_attribs; | |
| 417 va_res = vaQuerySurfaceAttributes( | |
| 418 va_display_, va_config_id, nullptr, &num_attribs); | |
| 419 VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false); | |
| 420 if (!num_attribs) | |
| 421 return false; | |
| 422 | |
| 423 std::vector<VASurfaceAttrib> attrib_list( | |
| 424 base::checked_cast<size_t>(num_attribs)); | |
| 425 | |
| 426 va_res = vaQuerySurfaceAttributes( | |
| 427 va_display_, va_config_id, &attrib_list[0], &num_attribs); | |
| 428 VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false); | |
| 429 | |
| 430 resolution->SetSize(0, 0); | |
| 431 for (const auto& attrib : attrib_list) { | |
| 432 if (attrib.type == VASurfaceAttribMaxWidth) | |
| 433 resolution->set_width(attrib.value.value.i); | |
| 434 else if (attrib.type == VASurfaceAttribMaxHeight) | |
| 435 resolution->set_height(attrib.value.value.i); | |
| 436 } | |
| 437 if (resolution->IsEmpty()) { | |
| 438 LOG(ERROR) << "Codec resolution " << resolution->ToString() | |
| 439 << " cannot be zero."; | |
| 440 return false; | |
| 441 } | |
| 442 return true; | |
| 443 } | |
| 444 | |
| 363 bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { | 445 bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { |
| 364 if (va_profile == VAProfileNone) { | 446 if (!profile_infos_.Get().IsProfileSupported(mode, va_profile)) { |
| 365 DVLOG(1) << "Unsupported profile"; | 447 DVLOG(1) << "Unsupported va profile: " << va_profile; |
| 366 return false; | 448 return false; |
| 367 } | 449 } |
| 368 VAEntrypoint entrypoint = | |
| 369 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | |
| 370 if (!IsEntrypointSupported(va_profile, entrypoint)) | |
| 371 return false; | |
| 372 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | |
| 373 if (!AreAttribsSupported(va_profile, entrypoint, required_attribs)) | |
| 374 return false; | |
| 375 | 450 |
| 376 TryToSetVADisplayAttributeToLocalGPU(); | 451 TryToSetVADisplayAttributeToLocalGPU(); |
| 377 | 452 |
| 453 VAEntrypoint entrypoint = | |
| 454 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | |
| 455 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | |
| 378 base::AutoLock auto_lock(va_lock_); | 456 base::AutoLock auto_lock(va_lock_); |
| 379 VAStatus va_res = vaCreateConfig(va_display_, | 457 VAStatus va_res = vaCreateConfig(va_display_, |
| 380 va_profile, | 458 va_profile, |
| 381 entrypoint, | 459 entrypoint, |
| 382 &required_attribs[0], | 460 &required_attribs[0], |
| 383 required_attribs.size(), | 461 required_attribs.size(), |
| 384 &va_config_id_); | 462 &va_config_id_); |
| 385 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); | 463 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); |
| 386 | 464 |
| 387 return true; | 465 return true; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 566 va_res = vaUnmapBuffer(va_display_, buffer_id); | 644 va_res = vaUnmapBuffer(va_display_, buffer_id); |
| 567 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 645 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
| 568 | 646 |
| 569 pending_va_bufs_.push_back(buffer_id); | 647 pending_va_bufs_.push_back(buffer_id); |
| 570 return true; | 648 return true; |
| 571 } | 649 } |
| 572 | 650 |
| 573 void VaapiWrapper::DestroyPendingBuffers() { | 651 void VaapiWrapper::DestroyPendingBuffers() { |
| 574 base::AutoLock auto_lock(va_lock_); | 652 base::AutoLock auto_lock(va_lock_); |
| 575 | 653 |
| 576 for (size_t i = 0; i < pending_va_bufs_.size(); ++i) { | 654 for (const auto& pending_va_buf : pending_va_bufs_) { |
| 577 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_bufs_[i]); | 655 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_buf); |
| 578 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 656 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
| 579 } | 657 } |
| 580 | 658 |
| 581 for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) { | 659 for (const auto& pending_slice_buf : pending_slice_bufs_) { |
| 582 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_bufs_[i]); | 660 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_buf); |
| 583 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 661 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
| 584 } | 662 } |
| 585 | 663 |
| 586 pending_va_bufs_.clear(); | 664 pending_va_bufs_.clear(); |
| 587 pending_slice_bufs_.clear(); | 665 pending_slice_bufs_.clear(); |
| 588 } | 666 } |
| 589 | 667 |
| 590 bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { | 668 bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { |
| 591 base::AutoLock auto_lock(va_lock_); | 669 base::AutoLock auto_lock(va_lock_); |
| 592 VAStatus va_res = vaCreateBuffer(va_display_, | 670 VAStatus va_res = vaCreateBuffer(va_display_, |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 952 | 1030 |
| 953 #if defined(USE_X11) | 1031 #if defined(USE_X11) |
| 954 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | 1032 paths[kModuleVa_x11].push_back("libva-x11.so.1"); |
| 955 #elif defined(USE_OZONE) | 1033 #elif defined(USE_OZONE) |
| 956 paths[kModuleVa_drm].push_back("libva-drm.so.1"); | 1034 paths[kModuleVa_drm].push_back("libva-drm.so.1"); |
| 957 #endif | 1035 #endif |
| 958 | 1036 |
| 959 return InitializeStubs(paths); | 1037 return InitializeStubs(paths); |
| 960 } | 1038 } |
| 961 | 1039 |
| 1040 VaapiWrapper::LazyProfileInfos::LazyProfileInfos() { | |
| 1041 static_assert(arraysize(supported_profiles_) == kCodecModeMax, | |
| 1042 "The array size of supported profile is incorrect."); | |
| 1043 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | |
| 1044 if (!vaapi_wrapper->VaInitialize(base::Bind(&base::DoNothing))) | |
| 1045 return; | |
| 1046 for (size_t i = 0; i < kCodecModeMax; ++i) { | |
| 1047 supported_profiles_[i] = | |
| 1048 vaapi_wrapper->GetSupportedProfileInfosForCodecModeInternal( | |
| 1049 static_cast<CodecMode>(i)); | |
| 1050 } | |
| 1051 } | |
| 1052 | |
| 1053 VaapiWrapper::LazyProfileInfos::~LazyProfileInfos() { | |
| 1054 } | |
| 1055 | |
| 1056 std::vector<VaapiWrapper::ProfileInfo> | |
| 1057 VaapiWrapper::LazyProfileInfos::GetSupportedProfileInfosForCodecMode( | |
| 1058 CodecMode mode) { | |
| 1059 return supported_profiles_[mode]; | |
| 1060 } | |
| 1061 | |
| 1062 bool VaapiWrapper::LazyProfileInfos::IsProfileSupported( | |
| 1063 CodecMode mode, VAProfile va_profile) { | |
| 1064 for (const auto& profile : supported_profiles_[mode]) { | |
| 1065 if (profile.va_profile == va_profile) | |
| 1066 return true; | |
| 1067 } | |
| 1068 return false; | |
| 1069 } | |
| 1070 | |
| 962 } // namespace content | 1071 } // namespace content |
| OLD | NEW |