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 static std::vector<VAConfigAttrib> GetRequiredAttribs( | |
61 VaapiWrapper::CodecMode mode) { | |
62 std::vector<VAConfigAttrib> required_attribs; | |
63 required_attribs.insert( | |
64 required_attribs.end(), | |
65 kCommonVAConfigAttribs, | |
66 kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs)); | |
67 if (mode == VaapiWrapper::kEncode) { | |
68 required_attribs.insert( | |
69 required_attribs.end(), | |
70 kEncodeVAConfigAttribs, | |
71 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); | |
72 } | |
73 return required_attribs; | |
74 } | |
75 | |
60 // Maps Profile enum values to VaProfile values. | 76 // Maps Profile enum values to VaProfile values. |
61 static VAProfile ProfileToVAProfile( | 77 static VAProfile ProfileToVAProfile( |
62 media::VideoCodecProfile profile, | 78 media::VideoCodecProfile profile, |
63 const std::vector<VAProfile>& supported_profiles) { | 79 const std::vector<VAProfile>& supported_profiles) { |
64 | 80 |
65 VAProfile va_profile = VAProfileNone; | 81 VAProfile va_profile = VAProfileNone; |
66 | 82 |
67 switch (profile) { | 83 switch (profile) { |
68 case media::H264PROFILE_BASELINE: | 84 case media::H264PROFILE_BASELINE: |
69 va_profile = VAProfileH264Baseline; | 85 va_profile = VAProfileH264Baseline; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 const base::Closure& report_error_to_uma_cb) { | 148 const base::Closure& report_error_to_uma_cb) { |
133 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 149 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
134 | 150 |
135 if (!vaapi_wrapper->Initialize( | 151 if (!vaapi_wrapper->Initialize( |
136 mode, profile, x_display, report_error_to_uma_cb)) | 152 mode, profile, x_display, report_error_to_uma_cb)) |
137 vaapi_wrapper.reset(); | 153 vaapi_wrapper.reset(); |
138 | 154 |
139 return vaapi_wrapper.Pass(); | 155 return vaapi_wrapper.Pass(); |
140 } | 156 } |
141 | 157 |
158 std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedProfiles( | |
159 Display* x_display, | |
160 const base::Closure& report_error_to_uma_cb) { | |
161 std::vector<media::VideoCodecProfile> supported_profiles; | |
162 media::VideoCodecProfile profiles[3] = {media::H264PROFILE_BASELINE, | |
Pawel Osciak
2014/09/26 07:15:12
Ideally we'd like to use all va_profiles and use s
wuchengli
2014/09/26 09:02:28
GetSupportedProfiles is called when GPU process st
| |
163 media::H264PROFILE_MAIN, | |
164 media::H264PROFILE_HIGH}; | |
165 | |
166 scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper()); | |
167 std::vector<VAProfile> va_profiles; | |
168 if (!wrapper->VaInitialize(x_display, report_error_to_uma_cb)) { | |
169 return supported_profiles; | |
170 } | |
171 if (!wrapper->GetSupportedVaProfiles(&va_profiles)) | |
172 return supported_profiles; | |
173 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode); | |
174 for (size_t i = 0; i < arraysize(profiles); i++) { | |
175 VAProfile va_profile = ProfileToVAProfile(profiles[i], va_profiles); | |
Pawel Osciak
2014/09/26 07:15:12
We have this chunk of code duplicated here and in
wuchengli
2014/09/26 09:02:28
Done.
vaCreateConfig needs VA profile, entrypoint
| |
176 if (va_profile != VAProfileNone && | |
177 wrapper->IsEntrypointSupported(va_profile, VAEntrypointEncSlice) && | |
178 wrapper->IsAttribSupported( | |
179 va_profile, VAEntrypointEncSlice, required_attribs)) { | |
180 supported_profiles.push_back(profiles[i]); | |
181 } | |
182 } | |
183 return supported_profiles; | |
184 } | |
185 | |
142 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { | 186 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
143 VADisplayAttribute item = {VADisplayAttribRenderMode, | 187 VADisplayAttribute item = {VADisplayAttribRenderMode, |
144 1, // At least support '_LOCAL_OVERLAY'. | 188 1, // At least support '_LOCAL_OVERLAY'. |
145 -1, // The maximum possible support 'ALL'. | 189 -1, // The maximum possible support 'ALL'. |
146 VA_RENDER_MODE_LOCAL_GPU, | 190 VA_RENDER_MODE_LOCAL_GPU, |
147 VA_DISPLAY_ATTRIB_SETTABLE}; | 191 VA_DISPLAY_ATTRIB_SETTABLE}; |
148 | 192 |
149 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 193 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
150 if (va_res != VA_STATUS_SUCCESS) | 194 if (va_res != VA_STATUS_SUCCESS) |
151 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 195 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
152 } | 196 } |
153 | 197 |
154 bool VaapiWrapper::Initialize(CodecMode mode, | 198 bool VaapiWrapper::VaInitialize(Display* x_display, |
155 media::VideoCodecProfile profile, | 199 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(); | 200 static bool vaapi_functions_initialized = PostSandboxInitialization(); |
159 if (!vaapi_functions_initialized) { | 201 if (!vaapi_functions_initialized) { |
160 DVLOG(1) << "Failed to initialize VAAPI libs"; | 202 DVLOG(1) << "Failed to initialize VAAPI libs"; |
161 return false; | 203 return false; |
162 } | 204 } |
163 | 205 |
164 report_error_to_uma_cb_ = report_error_to_uma_cb; | 206 report_error_to_uma_cb_ = report_error_to_uma_cb; |
165 | 207 |
166 base::AutoLock auto_lock(va_lock_); | 208 base::AutoLock auto_lock(va_lock_); |
167 | 209 |
168 va_display_ = vaGetDisplay(x_display); | 210 va_display_ = vaGetDisplay(x_display); |
169 if (!vaDisplayIsValid(va_display_)) { | 211 if (!vaDisplayIsValid(va_display_)) { |
170 DVLOG(1) << "Could not get a valid VA display"; | 212 DVLOG(1) << "Could not get a valid VA display"; |
171 return false; | 213 return false; |
172 } | 214 } |
173 | 215 |
174 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); | 216 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); |
175 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); | 217 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); |
176 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; | 218 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; |
177 | 219 |
178 if (VAAPIVersionLessThan(0, 34)) { | 220 if (VAAPIVersionLessThan(0, 34)) { |
179 DVLOG(1) << "VAAPI version < 0.34 is not supported."; | 221 DVLOG(1) << "VAAPI version < 0.34 is not supported."; |
180 return false; | 222 return false; |
181 } | 223 } |
224 return true; | |
225 } | |
182 | 226 |
227 bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) { | |
228 base::AutoLock auto_lock(va_lock_); | |
183 // Query the driver for supported profiles. | 229 // Query the driver for supported profiles. |
184 int max_profiles = vaMaxNumProfiles(va_display_); | 230 int max_profiles = vaMaxNumProfiles(va_display_); |
185 std::vector<VAProfile> supported_profiles( | 231 std::vector<VAProfile> supported_profiles( |
186 base::checked_cast<size_t>(max_profiles)); | 232 base::checked_cast<size_t>(max_profiles)); |
187 | 233 |
188 int num_supported_profiles; | 234 int num_supported_profiles; |
189 va_res = vaQueryConfigProfiles( | 235 VAStatus va_res = vaQueryConfigProfiles( |
190 va_display_, &supported_profiles[0], &num_supported_profiles); | 236 va_display_, &supported_profiles[0], &num_supported_profiles); |
191 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); | 237 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); |
192 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { | 238 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { |
193 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; | 239 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; |
194 return false; | 240 return false; |
195 } | 241 } |
196 | 242 |
197 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); | 243 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); |
244 *profiles = supported_profiles; | |
245 return true; | |
246 } | |
198 | 247 |
199 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); | 248 bool VaapiWrapper::IsEntrypointSupported(VAProfile va_profile, |
200 if (va_profile == VAProfileNone) { | 249 VAEntrypoint entrypoint) { |
201 DVLOG(1) << "Unsupported profile"; | 250 base::AutoLock auto_lock(va_lock_); |
202 return false; | |
203 } | |
204 | |
205 // Query the driver for supported entrypoints. | 251 // Query the driver for supported entrypoints. |
206 int max_entrypoints = vaMaxNumEntrypoints(va_display_); | 252 int max_entrypoints = vaMaxNumEntrypoints(va_display_); |
207 std::vector<VAEntrypoint> supported_entrypoints( | 253 std::vector<VAEntrypoint> supported_entrypoints( |
208 base::checked_cast<size_t>(max_entrypoints)); | 254 base::checked_cast<size_t>(max_entrypoints)); |
209 | 255 |
210 int num_supported_entrypoints; | 256 int num_supported_entrypoints; |
211 va_res = vaQueryConfigEntrypoints(va_display_, | 257 VAStatus va_res = vaQueryConfigEntrypoints(va_display_, |
212 va_profile, | 258 va_profile, |
213 &supported_entrypoints[0], | 259 &supported_entrypoints[0], |
214 &num_supported_entrypoints); | 260 &num_supported_entrypoints); |
215 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); | 261 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); |
216 if (num_supported_entrypoints < 0 || | 262 if (num_supported_entrypoints < 0 || |
217 num_supported_entrypoints > max_entrypoints) { | 263 num_supported_entrypoints > max_entrypoints) { |
218 DVLOG(1) << "vaQueryConfigEntrypoints returned: " | 264 DVLOG(1) << "vaQueryConfigEntrypoints returned: " |
219 << num_supported_entrypoints; | 265 << num_supported_entrypoints; |
220 return false; | 266 return false; |
221 } | 267 } |
222 | 268 |
223 VAEntrypoint entrypoint = | |
224 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | |
225 | |
226 if (std::find(supported_entrypoints.begin(), | 269 if (std::find(supported_entrypoints.begin(), |
227 supported_entrypoints.end(), | 270 supported_entrypoints.end(), |
228 entrypoint) == supported_entrypoints.end()) { | 271 entrypoint) == supported_entrypoints.end()) { |
229 DVLOG(1) << "Unsupported entrypoint"; | 272 DVLOG(1) << "Unsupported entrypoint"; |
230 return false; | 273 return false; |
231 } | 274 } |
275 return true; | |
276 } | |
232 | 277 |
278 bool VaapiWrapper::IsAttribSupported( | |
279 VAProfile va_profile, | |
280 VAEntrypoint entrypoint, | |
281 const std::vector<VAConfigAttrib>& required_attribs) { | |
282 base::AutoLock auto_lock(va_lock_); | |
233 // Query the driver for required attributes. | 283 // 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; | 284 std::vector<VAConfigAttrib> attribs = required_attribs; |
247 for (size_t i = 0; i < required_attribs.size(); ++i) | 285 for (size_t i = 0; i < required_attribs.size(); ++i) |
248 attribs[i].value = 0; | 286 attribs[i].value = 0; |
249 | 287 |
250 va_res = vaGetConfigAttributes( | 288 VAStatus va_res = vaGetConfigAttributes( |
251 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); | 289 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); |
252 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); | 290 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); |
253 | 291 |
254 for (size_t i = 0; i < required_attribs.size(); ++i) { | 292 for (size_t i = 0; i < required_attribs.size(); ++i) { |
255 if (attribs[i].type != required_attribs[i].type || | 293 if (attribs[i].type != required_attribs[i].type || |
256 (attribs[i].value & required_attribs[i].value) != | 294 (attribs[i].value & required_attribs[i].value) != |
257 required_attribs[i].value) { | 295 required_attribs[i].value) { |
258 DVLOG(1) << "Unsupported value " << required_attribs[i].value | 296 DVLOG(1) << "Unsupported value " << required_attribs[i].value |
259 << " for attribute type " << required_attribs[i].type; | 297 << " for attribute type " << required_attribs[i].type; |
260 return false; | 298 return false; |
261 } | 299 } |
262 } | 300 } |
301 return true; | |
302 } | |
303 | |
304 bool VaapiWrapper::Initialize(CodecMode mode, | |
305 media::VideoCodecProfile profile, | |
306 Display* x_display, | |
307 const base::Closure& report_error_to_uma_cb) { | |
308 if (!VaInitialize(x_display, report_error_to_uma_cb)) | |
309 return false; | |
310 std::vector<VAProfile> supported_profiles; | |
311 if (!GetSupportedVaProfiles(&supported_profiles)) | |
312 return false; | |
313 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); | |
314 if (va_profile == VAProfileNone) { | |
315 DVLOG(1) << "Unsupported profile"; | |
316 return false; | |
317 } | |
318 VAEntrypoint entrypoint = | |
319 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | |
320 if (!IsEntrypointSupported(va_profile, entrypoint)) | |
321 return false; | |
322 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | |
323 if (!IsAttribSupported(va_profile, entrypoint, required_attribs)) | |
324 return false; | |
263 | 325 |
264 TryToSetVADisplayAttributeToLocalGPU(); | 326 TryToSetVADisplayAttributeToLocalGPU(); |
265 | 327 |
266 va_res = vaCreateConfig(va_display_, | 328 VAStatus va_res = vaCreateConfig(va_display_, |
kcwu
2014/09/26 07:50:45
va_lock_ for this?
wuchengli
2014/09/26 09:02:28
Done. Thanks for catching this.
| |
267 va_profile, | 329 va_profile, |
268 entrypoint, | 330 entrypoint, |
269 &required_attribs[0], | 331 &required_attribs[0], |
270 required_attribs.size(), | 332 required_attribs.size(), |
271 &va_config_id_); | 333 &va_config_id_); |
272 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); | 334 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); |
273 | 335 |
274 return true; | 336 return true; |
275 } | 337 } |
276 | 338 |
277 void VaapiWrapper::Deinitialize() { | 339 void VaapiWrapper::Deinitialize() { |
278 base::AutoLock auto_lock(va_lock_); | 340 base::AutoLock auto_lock(va_lock_); |
279 | 341 |
280 if (va_config_id_ != VA_INVALID_ID) { | 342 if (va_config_id_ != VA_INVALID_ID) { |
281 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); | 343 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
667 | 729 |
668 // static | 730 // static |
669 bool VaapiWrapper::PostSandboxInitialization() { | 731 bool VaapiWrapper::PostSandboxInitialization() { |
670 StubPathMap paths; | 732 StubPathMap paths; |
671 paths[kModuleVa].push_back(kVaLib); | 733 paths[kModuleVa].push_back(kVaLib); |
672 | 734 |
673 return InitializeStubs(paths); | 735 return InitializeStubs(paths); |
674 } | 736 } |
675 | 737 |
676 } // namespace content | 738 } // namespace content |
OLD | NEW |