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; |
200 } | |
201 | |
202 // static | |
203 std::vector<VaapiWrapper::ProfileInfo> | |
204 VaapiWrapper::GetSupportedProfileInfosForCodecMode(CodecMode mode) { | |
205 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | |
206 if (!vaapi_wrapper->VaInitialize(base::Bind(&base::DoNothing))) | |
207 return std::vector<ProfileInfo>(); | |
208 return vaapi_wrapper->GetSupportedProfileInfosForCodecModeInternal(mode); | |
224 } | 209 } |
225 | 210 |
226 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { | 211 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
227 base::AutoLock auto_lock(va_lock_); | 212 base::AutoLock auto_lock(va_lock_); |
228 VADisplayAttribute item = {VADisplayAttribRenderMode, | 213 VADisplayAttribute item = {VADisplayAttribRenderMode, |
229 1, // At least support '_LOCAL_OVERLAY'. | 214 1, // At least support '_LOCAL_OVERLAY'. |
230 -1, // The maximum possible support 'ALL'. | 215 -1, // The maximum possible support 'ALL'. |
231 VA_RENDER_MODE_LOCAL_GPU, | 216 VA_RENDER_MODE_LOCAL_GPU, |
232 VA_DISPLAY_ATTRIB_SETTABLE}; | 217 VA_DISPLAY_ATTRIB_SETTABLE}; |
233 | 218 |
234 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 219 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
235 if (va_res != VA_STATUS_SUCCESS) | 220 if (va_res != VA_STATUS_SUCCESS) |
236 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 221 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
237 } | 222 } |
238 | 223 |
224 // static | |
225 VAProfile VaapiWrapper::ProfileToVAProfile( | |
226 media::VideoCodecProfile profile, CodecMode mode) { | |
227 VAProfile va_profile = VAProfileNone; | |
228 for (size_t i = 0; i < arraysize(kProfileMap); ++i) { | |
229 if (kProfileMap[i].profile == profile) { | |
230 va_profile = kProfileMap[i].va_profile; | |
231 break; | |
232 } | |
233 } | |
234 if (!profile_infos_.Get().IsProfileSupported(mode, va_profile) && | |
235 va_profile == VAProfileH264Baseline) { | |
236 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips | |
237 // the information whether the profile is constrained or not, so we have no | |
238 // way to know here. Try for baseline first, but if it is not supported, | |
239 // try constrained baseline and hope this is what it actually is | |
240 // (which in practice is true for a great majority of cases). | |
241 if (profile_infos_.Get().IsProfileSupported( | |
242 mode, VAProfileH264ConstrainedBaseline)) { | |
243 va_profile = VAProfileH264ConstrainedBaseline; | |
244 DVLOG(1) << "Fall back to constrained baseline profile."; | |
245 } | |
246 } | |
247 return va_profile; | |
248 } | |
249 | |
250 std::vector<VaapiWrapper::ProfileInfo> | |
251 VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) { | |
252 std::vector<ProfileInfo> supported_profile_infos; | |
253 std::vector<VAProfile> va_profiles; | |
254 if (!GetSupportedVaProfiles(&va_profiles)) | |
255 return supported_profile_infos; | |
256 | |
257 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | |
258 VAEntrypoint entrypoint = | |
259 (mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD); | |
260 | |
261 base::AutoLock auto_lock(va_lock_); | |
262 for (const auto& va_profile : va_profiles) { | |
263 if (!IsEntrypointSupported_Locked(va_profile, entrypoint)) | |
264 continue; | |
265 if (!AreAttribsSupported_Locked(va_profile, entrypoint, required_attribs)) | |
266 continue; | |
267 VAConfigID config_id; | |
268 VAStatus va_res = vaCreateConfig( | |
wuchengli
2015/03/09 05:17:30
Pawel and I discussed. vaCreateConfig should be mo
henryhsu
2015/03/09 09:21:53
Done.
| |
269 va_display_, | |
270 va_profile, | |
271 entrypoint, | |
272 &required_attribs[0], | |
273 required_attribs.size(), | |
274 &config_id); | |
275 if (va_res != VA_STATUS_SUCCESS) { | |
276 LOG_VA_ERROR_AND_REPORT(va_res, "vaCreateConfig failed"); | |
277 continue; | |
278 } | |
279 ProfileInfo profile_info; | |
280 if (!GetMaxResolutionForVAConfigID( | |
281 config_id, &profile_info.max_resolution)) { | |
282 LOG(ERROR) << "GetMaxResolution failed by va_profile " << va_profile; | |
283 continue; | |
284 } | |
285 profile_info.va_profile = va_profile; | |
286 supported_profile_infos.push_back(profile_info); | |
287 } | |
288 return supported_profile_infos; | |
289 } | |
290 | |
239 bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) { | 291 bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) { |
240 static bool vaapi_functions_initialized = PostSandboxInitialization(); | 292 static bool vaapi_functions_initialized = PostSandboxInitialization(); |
241 if (!vaapi_functions_initialized) { | 293 if (!vaapi_functions_initialized) { |
242 bool running_on_chromeos = false; | 294 bool running_on_chromeos = false; |
243 #if defined(OS_CHROMEOS) | 295 #if defined(OS_CHROMEOS) |
244 // When chrome runs on linux with chromeos=1, do not log error message | 296 // When chrome runs on linux with chromeos=1, do not log error message |
245 // without VAAPI libraries. | 297 // without VAAPI libraries. |
246 running_on_chromeos = base::SysInfo::IsRunningOnChromeOS(); | 298 running_on_chromeos = base::SysInfo::IsRunningOnChromeOS(); |
247 #endif | 299 #endif |
248 static const char kErrorMsg[] = "Failed to initialize VAAPI libs"; | 300 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) { | 349 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { |
298 LOG(ERROR) << "vaQueryConfigProfiles returned: " << num_supported_profiles; | 350 LOG(ERROR) << "vaQueryConfigProfiles returned: " << num_supported_profiles; |
299 return false; | 351 return false; |
300 } | 352 } |
301 | 353 |
302 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); | 354 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); |
303 *profiles = supported_profiles; | 355 *profiles = supported_profiles; |
304 return true; | 356 return true; |
305 } | 357 } |
306 | 358 |
307 bool VaapiWrapper::IsEntrypointSupported(VAProfile va_profile, | 359 bool VaapiWrapper::IsEntrypointSupported_Locked(VAProfile va_profile, |
308 VAEntrypoint entrypoint) { | 360 VAEntrypoint entrypoint) { |
309 base::AutoLock auto_lock(va_lock_); | 361 va_lock_.AssertAcquired(); |
310 // Query the driver for supported entrypoints. | 362 // Query the driver for supported entrypoints. |
311 int max_entrypoints = vaMaxNumEntrypoints(va_display_); | 363 int max_entrypoints = vaMaxNumEntrypoints(va_display_); |
312 std::vector<VAEntrypoint> supported_entrypoints( | 364 std::vector<VAEntrypoint> supported_entrypoints( |
313 base::checked_cast<size_t>(max_entrypoints)); | 365 base::checked_cast<size_t>(max_entrypoints)); |
314 | 366 |
315 int num_supported_entrypoints; | 367 int num_supported_entrypoints; |
316 VAStatus va_res = vaQueryConfigEntrypoints(va_display_, | 368 VAStatus va_res = vaQueryConfigEntrypoints(va_display_, |
317 va_profile, | 369 va_profile, |
318 &supported_entrypoints[0], | 370 &supported_entrypoints[0], |
319 &num_supported_entrypoints); | 371 &num_supported_entrypoints); |
320 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); | 372 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); |
321 if (num_supported_entrypoints < 0 || | 373 if (num_supported_entrypoints < 0 || |
322 num_supported_entrypoints > max_entrypoints) { | 374 num_supported_entrypoints > max_entrypoints) { |
323 LOG(ERROR) << "vaQueryConfigEntrypoints returned: " | 375 LOG(ERROR) << "vaQueryConfigEntrypoints returned: " |
324 << num_supported_entrypoints; | 376 << num_supported_entrypoints; |
325 return false; | 377 return false; |
326 } | 378 } |
327 | 379 |
328 if (std::find(supported_entrypoints.begin(), | 380 if (std::find(supported_entrypoints.begin(), |
329 supported_entrypoints.end(), | 381 supported_entrypoints.end(), |
330 entrypoint) == supported_entrypoints.end()) { | 382 entrypoint) == supported_entrypoints.end()) { |
331 DVLOG(1) << "Unsupported entrypoint"; | 383 DVLOG(1) << "Unsupported entrypoint"; |
332 return false; | 384 return false; |
333 } | 385 } |
334 return true; | 386 return true; |
335 } | 387 } |
336 | 388 |
337 bool VaapiWrapper::AreAttribsSupported( | 389 bool VaapiWrapper::AreAttribsSupported_Locked( |
338 VAProfile va_profile, | 390 VAProfile va_profile, |
339 VAEntrypoint entrypoint, | 391 VAEntrypoint entrypoint, |
340 const std::vector<VAConfigAttrib>& required_attribs) { | 392 const std::vector<VAConfigAttrib>& required_attribs) { |
341 base::AutoLock auto_lock(va_lock_); | 393 va_lock_.AssertAcquired(); |
342 // Query the driver for required attributes. | 394 // Query the driver for required attributes. |
343 std::vector<VAConfigAttrib> attribs = required_attribs; | 395 std::vector<VAConfigAttrib> attribs = required_attribs; |
344 for (size_t i = 0; i < required_attribs.size(); ++i) | 396 for (size_t i = 0; i < required_attribs.size(); ++i) |
345 attribs[i].value = 0; | 397 attribs[i].value = 0; |
346 | 398 |
347 VAStatus va_res = vaGetConfigAttributes( | 399 VAStatus va_res = vaGetConfigAttributes( |
348 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); | 400 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); |
349 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); | 401 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); |
350 | 402 |
351 for (size_t i = 0; i < required_attribs.size(); ++i) { | 403 for (size_t i = 0; i < required_attribs.size(); ++i) { |
352 if (attribs[i].type != required_attribs[i].type || | 404 if (attribs[i].type != required_attribs[i].type || |
353 (attribs[i].value & required_attribs[i].value) != | 405 (attribs[i].value & required_attribs[i].value) != |
354 required_attribs[i].value) { | 406 required_attribs[i].value) { |
355 DVLOG(1) << "Unsupported value " << required_attribs[i].value | 407 DVLOG(1) << "Unsupported value " << required_attribs[i].value |
356 << " for attribute type " << required_attribs[i].type; | 408 << " for attribute type " << required_attribs[i].type; |
357 return false; | 409 return false; |
358 } | 410 } |
359 } | 411 } |
360 return true; | 412 return true; |
361 } | 413 } |
362 | 414 |
415 bool VaapiWrapper::GetMaxResolutionForVAConfigID(VAConfigID va_config_id, | |
416 gfx::Size* resolution) { | |
417 va_lock_.AssertAcquired(); | |
418 unsigned int num_attribs; | |
419 | |
420 // Calls vaQuerySurfaceAttributes twice. The first time is to get the number | |
421 // of attributes to prepare the space and the second time is to get all | |
422 // attributes. | |
423 VAStatus va_res; | |
424 va_res = vaQuerySurfaceAttributes( | |
425 va_display_, va_config_id, nullptr, &num_attribs); | |
426 VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false); | |
427 if (!num_attribs) | |
428 return false; | |
429 | |
430 std::vector<VASurfaceAttrib> attrib_list( | |
431 base::checked_cast<size_t>(num_attribs)); | |
432 | |
433 va_res = vaQuerySurfaceAttributes( | |
434 va_display_, va_config_id, &attrib_list[0], &num_attribs); | |
435 VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false); | |
436 | |
437 resolution->SetSize(0, 0); | |
438 for (const auto& attrib : attrib_list) { | |
439 if (attrib.type == VASurfaceAttribMaxWidth) | |
440 resolution->set_width(attrib.value.value.i); | |
441 else if (attrib.type == VASurfaceAttribMaxHeight) | |
442 resolution->set_height(attrib.value.value.i); | |
443 } | |
444 if (resolution->IsEmpty()) { | |
445 LOG(ERROR) << "Codec resolution " << resolution->ToString() | |
446 << " cannot be zero."; | |
447 return false; | |
448 } | |
449 return true; | |
450 } | |
451 | |
363 bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { | 452 bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { |
364 if (va_profile == VAProfileNone) { | 453 if (!profile_infos_.Get().IsProfileSupported(mode, va_profile)) { |
365 DVLOG(1) << "Unsupported profile"; | 454 DVLOG(1) << "Unsupported va profile: " << va_profile; |
366 return false; | 455 return false; |
367 } | 456 } |
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 | 457 |
376 TryToSetVADisplayAttributeToLocalGPU(); | 458 TryToSetVADisplayAttributeToLocalGPU(); |
377 | 459 |
460 VAEntrypoint entrypoint = | |
461 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | |
462 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | |
378 base::AutoLock auto_lock(va_lock_); | 463 base::AutoLock auto_lock(va_lock_); |
379 VAStatus va_res = vaCreateConfig(va_display_, | 464 VAStatus va_res = vaCreateConfig(va_display_, |
380 va_profile, | 465 va_profile, |
381 entrypoint, | 466 entrypoint, |
382 &required_attribs[0], | 467 &required_attribs[0], |
383 required_attribs.size(), | 468 required_attribs.size(), |
384 &va_config_id_); | 469 &va_config_id_); |
385 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); | 470 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); |
386 | 471 |
387 return true; | 472 return true; |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
566 va_res = vaUnmapBuffer(va_display_, buffer_id); | 651 va_res = vaUnmapBuffer(va_display_, buffer_id); |
567 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 652 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
568 | 653 |
569 pending_va_bufs_.push_back(buffer_id); | 654 pending_va_bufs_.push_back(buffer_id); |
570 return true; | 655 return true; |
571 } | 656 } |
572 | 657 |
573 void VaapiWrapper::DestroyPendingBuffers() { | 658 void VaapiWrapper::DestroyPendingBuffers() { |
574 base::AutoLock auto_lock(va_lock_); | 659 base::AutoLock auto_lock(va_lock_); |
575 | 660 |
576 for (size_t i = 0; i < pending_va_bufs_.size(); ++i) { | 661 for (const auto& pending_va_buf : pending_va_bufs_) { |
577 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_bufs_[i]); | 662 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_buf); |
578 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 663 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
579 } | 664 } |
580 | 665 |
581 for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) { | 666 for (const auto& pending_slice_buf : pending_slice_bufs_) { |
582 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_bufs_[i]); | 667 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_buf); |
583 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 668 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
584 } | 669 } |
585 | 670 |
586 pending_va_bufs_.clear(); | 671 pending_va_bufs_.clear(); |
587 pending_slice_bufs_.clear(); | 672 pending_slice_bufs_.clear(); |
588 } | 673 } |
589 | 674 |
590 bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { | 675 bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { |
591 base::AutoLock auto_lock(va_lock_); | 676 base::AutoLock auto_lock(va_lock_); |
592 VAStatus va_res = vaCreateBuffer(va_display_, | 677 VAStatus va_res = vaCreateBuffer(va_display_, |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
952 | 1037 |
953 #if defined(USE_X11) | 1038 #if defined(USE_X11) |
954 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | 1039 paths[kModuleVa_x11].push_back("libva-x11.so.1"); |
955 #elif defined(USE_OZONE) | 1040 #elif defined(USE_OZONE) |
956 paths[kModuleVa_drm].push_back("libva-drm.so.1"); | 1041 paths[kModuleVa_drm].push_back("libva-drm.so.1"); |
957 #endif | 1042 #endif |
958 | 1043 |
959 return InitializeStubs(paths); | 1044 return InitializeStubs(paths); |
960 } | 1045 } |
961 | 1046 |
1047 VaapiWrapper::LazyProfileInfos::LazyProfileInfos() { | |
1048 static_assert(arraysize(supported_profiles_) == kCodecModeMax, | |
1049 "The array size of supported profile is incorrect."); | |
1050 for (size_t i = 0; i < kCodecModeMax; ++i) { | |
1051 supported_profiles_[i] = | |
1052 VaapiWrapper::GetSupportedProfileInfosForCodecMode( | |
1053 static_cast<CodecMode>(i)); | |
1054 } | |
1055 } | |
1056 | |
1057 VaapiWrapper::LazyProfileInfos::~LazyProfileInfos() { | |
1058 } | |
1059 | |
1060 std::vector<VaapiWrapper::ProfileInfo> | |
1061 VaapiWrapper::LazyProfileInfos::GetSupportedProfileInfosForCodecMode( | |
1062 CodecMode mode) { | |
1063 return supported_profiles_[mode]; | |
1064 } | |
1065 | |
1066 bool VaapiWrapper::LazyProfileInfos::IsProfileSupported( | |
1067 CodecMode mode, VAProfile va_profile) { | |
1068 for (const auto& profile : supported_profiles_[mode]) { | |
1069 if (profile.va_profile == va_profile) | |
1070 return true; | |
1071 } | |
1072 return false; | |
1073 } | |
1074 | |
962 } // namespace content | 1075 } // namespace content |
OLD | NEW |