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

Side by Side Diff: content/common/gpu/media/vaapi_wrapper.cc

Issue 603153002: vaapi: detect supported profiles in runtime. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rename to AreAttribsSupported and add va_lock_ to TryToSetVADisplayAttributeToLocalGPU Created 6 years, 2 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 unified diff | Download patch
« no previous file with comments | « content/common/gpu/media/vaapi_wrapper.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, 50 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420},
51 }; 51 };
52 52
53 // Attributes required for encode. 53 // Attributes required for encode.
54 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { 54 static const VAConfigAttrib kEncodeVAConfigAttribs[] = {
55 {VAConfigAttribRateControl, VA_RC_CBR}, 55 {VAConfigAttribRateControl, VA_RC_CBR},
56 {VAConfigAttribEncPackedHeaders, 56 {VAConfigAttribEncPackedHeaders,
57 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, 57 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE},
58 }; 58 };
59 59
60 struct ProfileMap {
61 media::VideoCodecProfile profile;
62 VAProfile va_profile;
63 };
64
65 // A map between VideoCodecProfile and VAProfile.
66 static const ProfileMap kProfileMap[] = {
67 {media::H264PROFILE_BASELINE, VAProfileH264Baseline},
68 {media::H264PROFILE_MAIN, VAProfileH264Main},
69 // TODO(posciak): See if we can/want support other variants of
70 // media::H264PROFILE_HIGH*.
71 {media::H264PROFILE_HIGH, VAProfileH264High},
72 };
73
74 static std::vector<VAConfigAttrib> GetRequiredAttribs(
75 VaapiWrapper::CodecMode mode) {
76 std::vector<VAConfigAttrib> required_attribs;
77 required_attribs.insert(
78 required_attribs.end(),
79 kCommonVAConfigAttribs,
80 kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs));
81 if (mode == VaapiWrapper::kEncode) {
82 required_attribs.insert(
83 required_attribs.end(),
84 kEncodeVAConfigAttribs,
85 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs));
86 }
87 return required_attribs;
88 }
89
60 // Maps Profile enum values to VaProfile values. 90 // Maps Profile enum values to VaProfile values.
61 static VAProfile ProfileToVAProfile( 91 static VAProfile ProfileToVAProfile(
62 media::VideoCodecProfile profile, 92 media::VideoCodecProfile profile,
63 const std::vector<VAProfile>& supported_profiles) { 93 const std::vector<VAProfile>& supported_profiles) {
64 94
65 VAProfile va_profile = VAProfileNone; 95 VAProfile va_profile = VAProfileNone;
66 96 for (size_t i = 0; i < arraysize(kProfileMap); i++) {
67 switch (profile) { 97 if (kProfileMap[i].profile == profile) {
68 case media::H264PROFILE_BASELINE: 98 va_profile = kProfileMap[i].va_profile;
69 va_profile = VAProfileH264Baseline;
70 break; 99 break;
71 case media::H264PROFILE_MAIN: 100 }
72 va_profile = VAProfileH264Main;
73 break;
74 // TODO(posciak): See if we can/want support other variants
75 // of media::H264PROFILE_HIGH*.
76 case media::H264PROFILE_HIGH:
77 va_profile = VAProfileH264High;
78 break;
79 default:
80 break;
81 } 101 }
82 102
83 bool supported = std::find(supported_profiles.begin(), 103 bool supported = std::find(supported_profiles.begin(),
84 supported_profiles.end(), 104 supported_profiles.end(),
85 va_profile) != supported_profiles.end(); 105 va_profile) != supported_profiles.end();
86 106
87 if (!supported && va_profile == VAProfileH264Baseline) { 107 if (!supported && va_profile == VAProfileH264Baseline) {
88 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips 108 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips
89 // the information whether the profile is constrained or not, so we have no 109 // the information whether the profile is constrained or not, so we have no
90 // way to know here. Try for baseline first, but if it is not supported, 110 // way to know here. Try for baseline first, but if it is not supported,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 const base::Closure& report_error_to_uma_cb) { 152 const base::Closure& report_error_to_uma_cb) {
133 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); 153 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper());
134 154
135 if (!vaapi_wrapper->Initialize( 155 if (!vaapi_wrapper->Initialize(
136 mode, profile, x_display, report_error_to_uma_cb)) 156 mode, profile, x_display, report_error_to_uma_cb))
137 vaapi_wrapper.reset(); 157 vaapi_wrapper.reset();
138 158
139 return vaapi_wrapper.Pass(); 159 return vaapi_wrapper.Pass();
140 } 160 }
141 161
162 std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles(
163 Display* x_display,
164 const base::Closure& report_error_to_uma_cb) {
165 std::vector<media::VideoCodecProfile> supported_profiles;
166
167 scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper());
168 if (!wrapper->VaInitialize(x_display, report_error_to_uma_cb)) {
169 return supported_profiles;
170 }
171
172 std::vector<VAProfile> va_profiles;
173 if (!wrapper->GetSupportedVaProfiles(&va_profiles))
174 return supported_profiles;
175
176 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode);
177 for (size_t i = 0; i < arraysize(kProfileMap); i++) {
178 VAProfile va_profile =
179 ProfileToVAProfile(kProfileMap[i].profile, va_profiles);
180 if (va_profile != VAProfileNone &&
181 wrapper->IsEntrypointSupported(va_profile, VAEntrypointEncSlice) &&
182 wrapper->AreAttribsSupported(
183 va_profile, VAEntrypointEncSlice, required_attribs)) {
184 supported_profiles.push_back(kProfileMap[i].profile);
185 }
186 }
187 return supported_profiles;
188 }
189
142 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { 190 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
191 base::AutoLock auto_lock(va_lock_);
143 VADisplayAttribute item = {VADisplayAttribRenderMode, 192 VADisplayAttribute item = {VADisplayAttribRenderMode,
144 1, // At least support '_LOCAL_OVERLAY'. 193 1, // At least support '_LOCAL_OVERLAY'.
145 -1, // The maximum possible support 'ALL'. 194 -1, // The maximum possible support 'ALL'.
146 VA_RENDER_MODE_LOCAL_GPU, 195 VA_RENDER_MODE_LOCAL_GPU,
147 VA_DISPLAY_ATTRIB_SETTABLE}; 196 VA_DISPLAY_ATTRIB_SETTABLE};
148 197
149 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); 198 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1);
150 if (va_res != VA_STATUS_SUCCESS) 199 if (va_res != VA_STATUS_SUCCESS)
151 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; 200 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default.";
152 } 201 }
153 202
154 bool VaapiWrapper::Initialize(CodecMode mode, 203 bool VaapiWrapper::VaInitialize(Display* x_display,
155 media::VideoCodecProfile profile, 204 const base::Closure& report_error_to_uma_cb) {
156 Display* x_display,
157 const base::Closure& report_error_to_uma_cb) {
158 static bool vaapi_functions_initialized = PostSandboxInitialization(); 205 static bool vaapi_functions_initialized = PostSandboxInitialization();
159 if (!vaapi_functions_initialized) { 206 if (!vaapi_functions_initialized) {
160 DVLOG(1) << "Failed to initialize VAAPI libs"; 207 DVLOG(1) << "Failed to initialize VAAPI libs";
161 return false; 208 return false;
162 } 209 }
163 210
164 report_error_to_uma_cb_ = report_error_to_uma_cb; 211 report_error_to_uma_cb_ = report_error_to_uma_cb;
165 212
166 base::AutoLock auto_lock(va_lock_); 213 base::AutoLock auto_lock(va_lock_);
167 214
168 va_display_ = vaGetDisplay(x_display); 215 va_display_ = vaGetDisplay(x_display);
169 if (!vaDisplayIsValid(va_display_)) { 216 if (!vaDisplayIsValid(va_display_)) {
170 DVLOG(1) << "Could not get a valid VA display"; 217 DVLOG(1) << "Could not get a valid VA display";
171 return false; 218 return false;
172 } 219 }
173 220
174 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); 221 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_);
175 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); 222 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false);
176 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; 223 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_;
177 224
178 if (VAAPIVersionLessThan(0, 34)) { 225 if (VAAPIVersionLessThan(0, 34)) {
179 DVLOG(1) << "VAAPI version < 0.34 is not supported."; 226 DVLOG(1) << "VAAPI version < 0.34 is not supported.";
180 return false; 227 return false;
181 } 228 }
229 return true;
230 }
182 231
232 bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) {
233 base::AutoLock auto_lock(va_lock_);
183 // Query the driver for supported profiles. 234 // Query the driver for supported profiles.
184 int max_profiles = vaMaxNumProfiles(va_display_); 235 int max_profiles = vaMaxNumProfiles(va_display_);
185 std::vector<VAProfile> supported_profiles( 236 std::vector<VAProfile> supported_profiles(
186 base::checked_cast<size_t>(max_profiles)); 237 base::checked_cast<size_t>(max_profiles));
187 238
188 int num_supported_profiles; 239 int num_supported_profiles;
189 va_res = vaQueryConfigProfiles( 240 VAStatus va_res = vaQueryConfigProfiles(
190 va_display_, &supported_profiles[0], &num_supported_profiles); 241 va_display_, &supported_profiles[0], &num_supported_profiles);
191 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); 242 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false);
192 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { 243 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) {
193 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; 244 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles;
194 return false; 245 return false;
195 } 246 }
196 247
197 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); 248 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles));
249 *profiles = supported_profiles;
250 return true;
251 }
198 252
199 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); 253 bool VaapiWrapper::IsEntrypointSupported(VAProfile va_profile,
200 if (va_profile == VAProfileNone) { 254 VAEntrypoint entrypoint) {
201 DVLOG(1) << "Unsupported profile"; 255 base::AutoLock auto_lock(va_lock_);
202 return false;
203 }
204
205 // Query the driver for supported entrypoints. 256 // Query the driver for supported entrypoints.
206 int max_entrypoints = vaMaxNumEntrypoints(va_display_); 257 int max_entrypoints = vaMaxNumEntrypoints(va_display_);
207 std::vector<VAEntrypoint> supported_entrypoints( 258 std::vector<VAEntrypoint> supported_entrypoints(
208 base::checked_cast<size_t>(max_entrypoints)); 259 base::checked_cast<size_t>(max_entrypoints));
209 260
210 int num_supported_entrypoints; 261 int num_supported_entrypoints;
211 va_res = vaQueryConfigEntrypoints(va_display_, 262 VAStatus va_res = vaQueryConfigEntrypoints(va_display_,
212 va_profile, 263 va_profile,
213 &supported_entrypoints[0], 264 &supported_entrypoints[0],
214 &num_supported_entrypoints); 265 &num_supported_entrypoints);
215 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); 266 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false);
216 if (num_supported_entrypoints < 0 || 267 if (num_supported_entrypoints < 0 ||
217 num_supported_entrypoints > max_entrypoints) { 268 num_supported_entrypoints > max_entrypoints) {
218 DVLOG(1) << "vaQueryConfigEntrypoints returned: " 269 DVLOG(1) << "vaQueryConfigEntrypoints returned: "
219 << num_supported_entrypoints; 270 << num_supported_entrypoints;
220 return false; 271 return false;
221 } 272 }
222 273
223 VAEntrypoint entrypoint =
224 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
225
226 if (std::find(supported_entrypoints.begin(), 274 if (std::find(supported_entrypoints.begin(),
227 supported_entrypoints.end(), 275 supported_entrypoints.end(),
228 entrypoint) == supported_entrypoints.end()) { 276 entrypoint) == supported_entrypoints.end()) {
229 DVLOG(1) << "Unsupported entrypoint"; 277 DVLOG(1) << "Unsupported entrypoint";
230 return false; 278 return false;
231 } 279 }
280 return true;
281 }
232 282
283 bool VaapiWrapper::AreAttribsSupported(
284 VAProfile va_profile,
285 VAEntrypoint entrypoint,
286 const std::vector<VAConfigAttrib>& required_attribs) {
287 base::AutoLock auto_lock(va_lock_);
233 // Query the driver for required attributes. 288 // Query the driver for required attributes.
234 std::vector<VAConfigAttrib> required_attribs;
235 required_attribs.insert(
236 required_attribs.end(),
237 kCommonVAConfigAttribs,
238 kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs));
239 if (mode == kEncode) {
240 required_attribs.insert(
241 required_attribs.end(),
242 kEncodeVAConfigAttribs,
243 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs));
244 }
245
246 std::vector<VAConfigAttrib> attribs = required_attribs; 289 std::vector<VAConfigAttrib> attribs = required_attribs;
247 for (size_t i = 0; i < required_attribs.size(); ++i) 290 for (size_t i = 0; i < required_attribs.size(); ++i)
248 attribs[i].value = 0; 291 attribs[i].value = 0;
249 292
250 va_res = vaGetConfigAttributes( 293 VAStatus va_res = vaGetConfigAttributes(
251 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); 294 va_display_, va_profile, entrypoint, &attribs[0], attribs.size());
252 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); 295 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false);
253 296
254 for (size_t i = 0; i < required_attribs.size(); ++i) { 297 for (size_t i = 0; i < required_attribs.size(); ++i) {
255 if (attribs[i].type != required_attribs[i].type || 298 if (attribs[i].type != required_attribs[i].type ||
256 (attribs[i].value & required_attribs[i].value) != 299 (attribs[i].value & required_attribs[i].value) !=
257 required_attribs[i].value) { 300 required_attribs[i].value) {
258 DVLOG(1) << "Unsupported value " << required_attribs[i].value 301 DVLOG(1) << "Unsupported value " << required_attribs[i].value
259 << " for attribute type " << required_attribs[i].type; 302 << " for attribute type " << required_attribs[i].type;
260 return false; 303 return false;
261 } 304 }
262 } 305 }
306 return true;
307 }
308
309 bool VaapiWrapper::Initialize(CodecMode mode,
310 media::VideoCodecProfile profile,
311 Display* x_display,
312 const base::Closure& report_error_to_uma_cb) {
313 if (!VaInitialize(x_display, report_error_to_uma_cb))
314 return false;
315 std::vector<VAProfile> supported_va_profiles;
316 if (!GetSupportedVaProfiles(&supported_va_profiles))
317 return false;
318 VAProfile va_profile = ProfileToVAProfile(profile, supported_va_profiles);
319 if (va_profile == VAProfileNone) {
320 DVLOG(1) << "Unsupported profile";
321 return false;
322 }
323 VAEntrypoint entrypoint =
324 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
325 if (!IsEntrypointSupported(va_profile, entrypoint))
326 return false;
327 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode);
328 if (!AreAttribsSupported(va_profile, entrypoint, required_attribs))
329 return false;
263 330
264 TryToSetVADisplayAttributeToLocalGPU(); 331 TryToSetVADisplayAttributeToLocalGPU();
265 332
266 va_res = vaCreateConfig(va_display_, 333 base::AutoLock auto_lock(va_lock_);
267 va_profile, 334 VAStatus va_res = vaCreateConfig(va_display_,
268 entrypoint, 335 va_profile,
269 &required_attribs[0], 336 entrypoint,
270 required_attribs.size(), 337 &required_attribs[0],
271 &va_config_id_); 338 required_attribs.size(),
339 &va_config_id_);
272 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); 340 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false);
273 341
274 return true; 342 return true;
275 } 343 }
276 344
277 void VaapiWrapper::Deinitialize() { 345 void VaapiWrapper::Deinitialize() {
278 base::AutoLock auto_lock(va_lock_); 346 base::AutoLock auto_lock(va_lock_);
279 347
280 if (va_config_id_ != VA_INVALID_ID) { 348 if (va_config_id_ != VA_INVALID_ID) {
281 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); 349 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_);
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 735
668 // static 736 // static
669 bool VaapiWrapper::PostSandboxInitialization() { 737 bool VaapiWrapper::PostSandboxInitialization() {
670 StubPathMap paths; 738 StubPathMap paths;
671 paths[kModuleVa].push_back(kVaLib); 739 paths[kModuleVa].push_back(kVaLib);
672 740
673 return InitializeStubs(paths); 741 return InitializeStubs(paths);
674 } 742 }
675 743
676 } // namespace content 744 } // namespace content
OLDNEW
« no previous file with comments | « 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