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" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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}}; | |
kcwu
2014/09/26 10:06:14
how about }; in next line
| |
72 | |
73 static std::vector<VAConfigAttrib> GetRequiredAttribs( | |
74 VaapiWrapper::CodecMode mode) { | |
75 std::vector<VAConfigAttrib> required_attribs; | |
76 required_attribs.insert( | |
77 required_attribs.end(), | |
78 kCommonVAConfigAttribs, | |
79 kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs)); | |
80 if (mode == VaapiWrapper::kEncode) { | |
81 required_attribs.insert( | |
82 required_attribs.end(), | |
83 kEncodeVAConfigAttribs, | |
84 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); | |
85 } | |
86 return required_attribs; | |
87 } | |
88 | |
60 // Maps Profile enum values to VaProfile values. | 89 // Maps Profile enum values to VaProfile values. |
61 static VAProfile ProfileToVAProfile( | 90 static VAProfile ProfileToVAProfile( |
62 media::VideoCodecProfile profile, | 91 media::VideoCodecProfile profile, |
63 const std::vector<VAProfile>& supported_profiles) { | 92 const std::vector<VAProfile>& supported_profiles) { |
64 | 93 |
65 VAProfile va_profile = VAProfileNone; | 94 VAProfile va_profile = VAProfileNone; |
66 | 95 for (size_t i = 0; i < arraysize(kProfileMap); i++) { |
67 switch (profile) { | 96 if (kProfileMap[i].profile == profile) { |
68 case media::H264PROFILE_BASELINE: | 97 va_profile = kProfileMap[i].va_profile; |
69 va_profile = VAProfileH264Baseline; | |
70 break; | 98 break; |
71 case media::H264PROFILE_MAIN: | 99 } |
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 } | 100 } |
82 | 101 |
83 bool supported = std::find(supported_profiles.begin(), | 102 bool supported = std::find(supported_profiles.begin(), |
84 supported_profiles.end(), | 103 supported_profiles.end(), |
85 va_profile) != supported_profiles.end(); | 104 va_profile) != supported_profiles.end(); |
86 | 105 |
87 if (!supported && va_profile == VAProfileH264Baseline) { | 106 if (!supported && va_profile == VAProfileH264Baseline) { |
88 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips | 107 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips |
89 // the information whether the profile is constrained or not, so we have no | 108 // 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, | 109 // 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 Loading... | |
132 const base::Closure& report_error_to_uma_cb) { | 151 const base::Closure& report_error_to_uma_cb) { |
133 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 152 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
134 | 153 |
135 if (!vaapi_wrapper->Initialize( | 154 if (!vaapi_wrapper->Initialize( |
136 mode, profile, x_display, report_error_to_uma_cb)) | 155 mode, profile, x_display, report_error_to_uma_cb)) |
137 vaapi_wrapper.reset(); | 156 vaapi_wrapper.reset(); |
138 | 157 |
139 return vaapi_wrapper.Pass(); | 158 return vaapi_wrapper.Pass(); |
140 } | 159 } |
141 | 160 |
161 std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles( | |
162 Display* x_display, | |
163 const base::Closure& report_error_to_uma_cb) { | |
164 std::vector<media::VideoCodecProfile> supported_profiles; | |
165 | |
166 scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper()); | |
167 if (!wrapper->VaInitialize(x_display, report_error_to_uma_cb)) { | |
168 return supported_profiles; | |
169 } | |
170 | |
171 std::vector<VAProfile> va_profiles; | |
172 if (!wrapper->GetSupportedVaProfiles(&va_profiles)) | |
173 return supported_profiles; | |
174 | |
175 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode); | |
176 for (size_t i = 0; i < arraysize(kProfileMap); i++) { | |
177 VAProfile va_profile = VAProfileNone; | |
178 if (wrapper->IsProfileSupported(kProfileMap[i].profile, | |
179 va_profiles, | |
180 VAEntrypointEncSlice, | |
181 required_attribs, | |
182 &va_profile)) { | |
183 supported_profiles.push_back(kProfileMap[i].profile); | |
184 } | |
185 } | |
186 return supported_profiles; | |
187 } | |
188 | |
142 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { | 189 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
143 VADisplayAttribute item = {VADisplayAttribRenderMode, | 190 VADisplayAttribute item = {VADisplayAttribRenderMode, |
144 1, // At least support '_LOCAL_OVERLAY'. | 191 1, // At least support '_LOCAL_OVERLAY'. |
145 -1, // The maximum possible support 'ALL'. | 192 -1, // The maximum possible support 'ALL'. |
146 VA_RENDER_MODE_LOCAL_GPU, | 193 VA_RENDER_MODE_LOCAL_GPU, |
147 VA_DISPLAY_ATTRIB_SETTABLE}; | 194 VA_DISPLAY_ATTRIB_SETTABLE}; |
148 | 195 |
149 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 196 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
150 if (va_res != VA_STATUS_SUCCESS) | 197 if (va_res != VA_STATUS_SUCCESS) |
151 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 198 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
152 } | 199 } |
153 | 200 |
154 bool VaapiWrapper::Initialize(CodecMode mode, | 201 bool VaapiWrapper::VaInitialize(Display* x_display, |
155 media::VideoCodecProfile profile, | 202 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(); | 203 static bool vaapi_functions_initialized = PostSandboxInitialization(); |
159 if (!vaapi_functions_initialized) { | 204 if (!vaapi_functions_initialized) { |
160 DVLOG(1) << "Failed to initialize VAAPI libs"; | 205 DVLOG(1) << "Failed to initialize VAAPI libs"; |
161 return false; | 206 return false; |
162 } | 207 } |
163 | 208 |
164 report_error_to_uma_cb_ = report_error_to_uma_cb; | 209 report_error_to_uma_cb_ = report_error_to_uma_cb; |
165 | 210 |
166 base::AutoLock auto_lock(va_lock_); | 211 base::AutoLock auto_lock(va_lock_); |
167 | 212 |
168 va_display_ = vaGetDisplay(x_display); | 213 va_display_ = vaGetDisplay(x_display); |
169 if (!vaDisplayIsValid(va_display_)) { | 214 if (!vaDisplayIsValid(va_display_)) { |
170 DVLOG(1) << "Could not get a valid VA display"; | 215 DVLOG(1) << "Could not get a valid VA display"; |
171 return false; | 216 return false; |
172 } | 217 } |
173 | 218 |
174 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); | 219 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); |
175 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); | 220 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); |
176 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; | 221 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; |
177 | 222 |
178 if (VAAPIVersionLessThan(0, 34)) { | 223 if (VAAPIVersionLessThan(0, 34)) { |
179 DVLOG(1) << "VAAPI version < 0.34 is not supported."; | 224 DVLOG(1) << "VAAPI version < 0.34 is not supported."; |
180 return false; | 225 return false; |
181 } | 226 } |
227 return true; | |
228 } | |
182 | 229 |
230 bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) { | |
231 base::AutoLock auto_lock(va_lock_); | |
183 // Query the driver for supported profiles. | 232 // Query the driver for supported profiles. |
184 int max_profiles = vaMaxNumProfiles(va_display_); | 233 int max_profiles = vaMaxNumProfiles(va_display_); |
185 std::vector<VAProfile> supported_profiles( | 234 std::vector<VAProfile> supported_profiles( |
186 base::checked_cast<size_t>(max_profiles)); | 235 base::checked_cast<size_t>(max_profiles)); |
187 | 236 |
188 int num_supported_profiles; | 237 int num_supported_profiles; |
189 va_res = vaQueryConfigProfiles( | 238 VAStatus va_res = vaQueryConfigProfiles( |
190 va_display_, &supported_profiles[0], &num_supported_profiles); | 239 va_display_, &supported_profiles[0], &num_supported_profiles); |
191 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); | 240 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); |
192 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { | 241 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { |
193 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; | 242 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; |
194 return false; | 243 return false; |
195 } | 244 } |
196 | 245 |
197 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); | 246 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); |
247 *profiles = supported_profiles; | |
248 return true; | |
249 } | |
198 | 250 |
199 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); | 251 bool VaapiWrapper::IsProfileSupported( |
200 if (va_profile == VAProfileNone) { | 252 media::VideoCodecProfile profile, |
253 const std::vector<VAProfile>& supported_profiles, | |
254 VAEntrypoint entrypoint, | |
255 const std::vector<VAConfigAttrib>& required_attribs, | |
256 VAProfile* va_profile) { | |
257 *va_profile = ProfileToVAProfile(profile, supported_profiles); | |
258 if (*va_profile == VAProfileNone) { | |
201 DVLOG(1) << "Unsupported profile"; | 259 DVLOG(1) << "Unsupported profile"; |
202 return false; | 260 return false; |
203 } | 261 } |
204 | 262 |
263 base::AutoLock auto_lock(va_lock_); | |
205 // Query the driver for supported entrypoints. | 264 // Query the driver for supported entrypoints. |
206 int max_entrypoints = vaMaxNumEntrypoints(va_display_); | 265 int max_entrypoints = vaMaxNumEntrypoints(va_display_); |
207 std::vector<VAEntrypoint> supported_entrypoints( | 266 std::vector<VAEntrypoint> supported_entrypoints( |
208 base::checked_cast<size_t>(max_entrypoints)); | 267 base::checked_cast<size_t>(max_entrypoints)); |
209 | 268 |
210 int num_supported_entrypoints; | 269 int num_supported_entrypoints; |
211 va_res = vaQueryConfigEntrypoints(va_display_, | 270 VAStatus va_res = vaQueryConfigEntrypoints(va_display_, |
212 va_profile, | 271 *va_profile, |
213 &supported_entrypoints[0], | 272 &supported_entrypoints[0], |
214 &num_supported_entrypoints); | 273 &num_supported_entrypoints); |
215 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); | 274 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); |
216 if (num_supported_entrypoints < 0 || | 275 if (num_supported_entrypoints < 0 || |
217 num_supported_entrypoints > max_entrypoints) { | 276 num_supported_entrypoints > max_entrypoints) { |
218 DVLOG(1) << "vaQueryConfigEntrypoints returned: " | 277 DVLOG(1) << "vaQueryConfigEntrypoints returned: " |
219 << num_supported_entrypoints; | 278 << num_supported_entrypoints; |
220 return false; | 279 return false; |
221 } | 280 } |
222 | 281 |
223 VAEntrypoint entrypoint = | |
224 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | |
225 | |
226 if (std::find(supported_entrypoints.begin(), | 282 if (std::find(supported_entrypoints.begin(), |
227 supported_entrypoints.end(), | 283 supported_entrypoints.end(), |
228 entrypoint) == supported_entrypoints.end()) { | 284 entrypoint) == supported_entrypoints.end()) { |
229 DVLOG(1) << "Unsupported entrypoint"; | 285 DVLOG(1) << "Unsupported entrypoint"; |
230 return false; | 286 return false; |
231 } | 287 } |
232 | 288 |
233 // Query the driver for required attributes. | 289 // 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; | 290 std::vector<VAConfigAttrib> attribs = required_attribs; |
247 for (size_t i = 0; i < required_attribs.size(); ++i) | 291 for (size_t i = 0; i < required_attribs.size(); ++i) |
248 attribs[i].value = 0; | 292 attribs[i].value = 0; |
249 | 293 |
250 va_res = vaGetConfigAttributes( | 294 va_res = vaGetConfigAttributes( |
251 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); | 295 va_display_, *va_profile, entrypoint, &attribs[0], attribs.size()); |
252 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); | 296 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); |
253 | 297 |
254 for (size_t i = 0; i < required_attribs.size(); ++i) { | 298 for (size_t i = 0; i < required_attribs.size(); ++i) { |
255 if (attribs[i].type != required_attribs[i].type || | 299 if (attribs[i].type != required_attribs[i].type || |
256 (attribs[i].value & required_attribs[i].value) != | 300 (attribs[i].value & required_attribs[i].value) != |
257 required_attribs[i].value) { | 301 required_attribs[i].value) { |
258 DVLOG(1) << "Unsupported value " << required_attribs[i].value | 302 DVLOG(1) << "Unsupported value " << required_attribs[i].value |
259 << " for attribute type " << required_attribs[i].type; | 303 << " for attribute type " << required_attribs[i].type; |
260 return false; | 304 return false; |
261 } | 305 } |
262 } | 306 } |
307 return true; | |
308 } | |
263 | 309 |
310 bool VaapiWrapper::Initialize(CodecMode mode, | |
311 media::VideoCodecProfile profile, | |
312 Display* x_display, | |
313 const base::Closure& report_error_to_uma_cb) { | |
314 if (!VaInitialize(x_display, report_error_to_uma_cb)) | |
315 return false; | |
316 std::vector<VAProfile> supported_va_profiles; | |
317 if (!GetSupportedVaProfiles(&supported_va_profiles)) | |
318 return false; | |
319 VAEntrypoint entrypoint = | |
320 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | |
321 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | |
322 VAProfile va_profile = VAProfileNone; | |
323 if (!IsProfileSupported(profile, | |
324 supported_va_profiles, | |
325 entrypoint, | |
326 required_attribs, | |
327 &va_profile)) { | |
328 return false; | |
329 } | |
330 | |
331 base::AutoLock auto_lock(va_lock_); | |
264 TryToSetVADisplayAttributeToLocalGPU(); | 332 TryToSetVADisplayAttributeToLocalGPU(); |
265 | 333 |
266 va_res = vaCreateConfig(va_display_, | 334 VAStatus va_res = vaCreateConfig(va_display_, |
267 va_profile, | 335 va_profile, |
268 entrypoint, | 336 entrypoint, |
269 &required_attribs[0], | 337 &required_attribs[0], |
270 required_attribs.size(), | 338 required_attribs.size(), |
271 &va_config_id_); | 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 Loading... | |
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 |
OLD | NEW |