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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
49 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ | 49 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ |
50 do { \ | 50 do { \ |
51 if ((va_error) != VA_STATUS_SUCCESS) { \ | 51 if ((va_error) != VA_STATUS_SUCCESS) { \ |
52 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ | 52 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ |
53 return (ret); \ | 53 return (ret); \ |
54 } \ | 54 } \ |
55 } while (0) | 55 } while (0) |
56 | 56 |
57 namespace content { | 57 namespace content { |
58 | 58 |
59 bool VaapiWrapper::is_initialize_profile_; | |
60 VaapiWrapper::ProfileConfig | |
61 VaapiWrapper::supported_profiles_[media::VIDEO_CODEC_PROFILE_MAX * 2] = | |
kcwu
2015/02/02 10:11:01
MAX*2+1
henryhsu
2015/02/13 04:01:03
Not used anymore
| |
62 {{media::VIDEO_CODEC_PROFILE_UNKNOWN}}; | |
kcwu
2015/02/02 10:11:01
add comment that UNKNOWN is guard.
henryhsu
2015/02/13 04:01:03
Not used anymore
| |
63 | |
59 // Config attributes common for both encode and decode. | 64 // Config attributes common for both encode and decode. |
60 static const VAConfigAttrib kCommonVAConfigAttribs[] = { | 65 static const VAConfigAttrib kCommonVAConfigAttribs[] = { |
61 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, | 66 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, |
62 }; | 67 }; |
63 | 68 |
64 // Attributes required for encode. | 69 // Attributes required for encode. |
65 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { | 70 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { |
66 {VAConfigAttribRateControl, VA_RC_CBR}, | 71 {VAConfigAttribRateControl, VA_RC_CBR}, |
67 {VAConfigAttribEncPackedHeaders, | 72 {VAConfigAttribEncPackedHeaders, |
68 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, | 73 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, |
(...skipping 23 matching lines...) Expand all Loading... | |
92 if (mode == VaapiWrapper::kEncode) { | 97 if (mode == VaapiWrapper::kEncode) { |
93 required_attribs.insert( | 98 required_attribs.insert( |
94 required_attribs.end(), | 99 required_attribs.end(), |
95 kEncodeVAConfigAttribs, | 100 kEncodeVAConfigAttribs, |
96 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); | 101 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); |
97 } | 102 } |
98 return required_attribs; | 103 return required_attribs; |
99 } | 104 } |
100 | 105 |
101 // Maps Profile enum values to VaProfile values. | 106 // Maps Profile enum values to VaProfile values. |
102 static VAProfile ProfileToVAProfile( | 107 static VAProfile ProfileToVAProfile(media::VideoCodecProfile profile) { |
103 media::VideoCodecProfile profile, | |
104 const std::vector<VAProfile>& supported_profiles) { | |
105 | |
106 VAProfile va_profile = VAProfileNone; | 108 VAProfile va_profile = VAProfileNone; |
107 for (size_t i = 0; i < arraysize(kProfileMap); i++) { | 109 for (size_t i = 0; i < arraysize(kProfileMap); i++) { |
108 if (kProfileMap[i].profile == profile) { | 110 if (kProfileMap[i].profile == profile) { |
109 va_profile = kProfileMap[i].va_profile; | 111 va_profile = kProfileMap[i].va_profile; |
110 break; | 112 break; |
111 } | 113 } |
112 } | 114 } |
115 return va_profile; | |
116 } | |
113 | 117 |
118 // checks VaProfile is supported. | |
119 static VAProfile GetSupportedVaProfile( | |
120 VAProfile va_profile, | |
121 const std::vector<VAProfile>& supported_profiles) { | |
114 bool supported = std::find(supported_profiles.begin(), | 122 bool supported = std::find(supported_profiles.begin(), |
115 supported_profiles.end(), | 123 supported_profiles.end(), |
116 va_profile) != supported_profiles.end(); | 124 va_profile) != supported_profiles.end(); |
117 | 125 |
118 if (!supported && va_profile == VAProfileH264Baseline) { | 126 if (!supported) { |
119 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips | 127 if (va_profile == VAProfileH264Baseline) { |
120 // the information whether the profile is constrained or not, so we have no | 128 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently |
121 // way to know here. Try for baseline first, but if it is not supported, | 129 // strips the information whether the profile is constrained or not, so we |
122 // try constrained baseline and hope this is what it actually is | 130 // have no way to know here. Try for baseline first, but if it is not |
123 // (which in practice is true for a great majority of cases). | 131 // supported, try constrained baseline and hope this is what it actually |
124 if (std::find(supported_profiles.begin(), | 132 // is (which in practice is true for a great majority of cases). |
125 supported_profiles.end(), | 133 if (std::find(supported_profiles.begin(), |
126 VAProfileH264ConstrainedBaseline) != | 134 supported_profiles.end(), |
127 supported_profiles.end()) { | 135 VAProfileH264ConstrainedBaseline) != |
128 va_profile = VAProfileH264ConstrainedBaseline; | 136 supported_profiles.end()) { |
129 DVLOG(1) << "Falling back to constrained baseline profile."; | 137 va_profile = VAProfileH264ConstrainedBaseline; |
138 DVLOG(1) << "Falling back to constrained baseline profile."; | |
139 } | |
140 } else { | |
141 va_profile = VAProfileNone; | |
130 } | 142 } |
131 } | 143 } |
132 | 144 |
133 return va_profile; | 145 return va_profile; |
134 } | 146 } |
135 | 147 |
136 VASurface::VASurface(VASurfaceID va_surface_id, | 148 VASurface::VASurface(VASurfaceID va_surface_id, |
137 const gfx::Size& size, | 149 const gfx::Size& size, |
138 const ReleaseCB& release_cb) | 150 const ReleaseCB& release_cb) |
139 : va_surface_id_(va_surface_id), size_(size), release_cb_(release_cb) { | 151 : va_surface_id_(va_surface_id), size_(size), release_cb_(release_cb) { |
(...skipping 15 matching lines...) Expand all Loading... | |
155 } | 167 } |
156 | 168 |
157 VaapiWrapper::~VaapiWrapper() { | 169 VaapiWrapper::~VaapiWrapper() { |
158 DestroyPendingBuffers(); | 170 DestroyPendingBuffers(); |
159 DestroyCodedBuffers(); | 171 DestroyCodedBuffers(); |
160 DestroySurfaces(); | 172 DestroySurfaces(); |
161 DeinitializeVpp(); | 173 DeinitializeVpp(); |
162 Deinitialize(); | 174 Deinitialize(); |
163 } | 175 } |
164 | 176 |
177 // static | |
178 scoped_ptr<VaapiWrapper> VaapiWrapper::CreateInstance( | |
179 const base::Closure& report_error_to_uma_cb) { | |
180 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | |
181 if (!vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) | |
182 vaapi_wrapper.reset(); | |
183 else | |
184 vaapi_wrapper->InitializeSupportedProfiles(); | |
185 return vaapi_wrapper.Pass(); | |
186 } | |
187 | |
188 // static | |
165 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( | 189 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( |
kcwu
2015/02/02 10:11:01
you need to rebase since I modified these function
henryhsu
2015/02/13 04:01:03
Done.
| |
166 CodecMode mode, | 190 CodecMode mode, |
167 media::VideoCodecProfile profile, | 191 media::VideoCodecProfile profile, |
168 const base::Closure& report_error_to_uma_cb) { | 192 const base::Closure& report_error_to_uma_cb) { |
169 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 193 scoped_ptr<VaapiWrapper> vaapi_wrapper = |
194 CreateInstance(report_error_to_uma_cb); | |
170 | 195 |
171 if (!vaapi_wrapper->Initialize(mode, profile, report_error_to_uma_cb)) | 196 if (vaapi_wrapper && |
197 !vaapi_wrapper->Initialize(mode, profile)) | |
172 vaapi_wrapper.reset(); | 198 vaapi_wrapper.reset(); |
173 | 199 |
174 return vaapi_wrapper.Pass(); | 200 return vaapi_wrapper.Pass(); |
175 } | 201 } |
176 | 202 |
177 std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles( | 203 // static |
178 const base::Closure& report_error_to_uma_cb) { | 204 std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedProfiles( |
205 CodecMode mode) { | |
179 std::vector<media::VideoCodecProfile> supported_profiles; | 206 std::vector<media::VideoCodecProfile> supported_profiles; |
180 | 207 if (!CreateInstance(base::Bind(&base::DoNothing))) |
181 scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper()); | |
182 if (!wrapper->VaInitialize(report_error_to_uma_cb)) { | |
183 return supported_profiles; | 208 return supported_profiles; |
184 } | 209 for (size_t i = 0; |
185 | 210 supported_profiles_[i].profile != media::VIDEO_CODEC_PROFILE_UNKNOWN; |
186 std::vector<VAProfile> va_profiles; | 211 ++i) { |
187 if (!wrapper->GetSupportedVaProfiles(&va_profiles)) | 212 if (supported_profiles_[i].mode == mode) |
188 return supported_profiles; | 213 supported_profiles.push_back(supported_profiles_[i].profile); |
189 | |
190 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode); | |
191 for (size_t i = 0; i < arraysize(kProfileMap); i++) { | |
192 VAProfile va_profile = | |
193 ProfileToVAProfile(kProfileMap[i].profile, va_profiles); | |
194 if (va_profile != VAProfileNone && | |
195 wrapper->IsEntrypointSupported(va_profile, VAEntrypointEncSlice) && | |
196 wrapper->AreAttribsSupported( | |
197 va_profile, VAEntrypointEncSlice, required_attribs)) { | |
198 supported_profiles.push_back(kProfileMap[i].profile); | |
199 } | |
200 } | 214 } |
201 return supported_profiles; | 215 return supported_profiles; |
202 } | 216 } |
203 | 217 |
218 // static | |
219 gfx::Size VaapiWrapper::GetCodecMaxResolution( | |
220 media::VideoCodecProfile profile, | |
221 CodecMode mode) { | |
222 if (!CreateInstance(base::Bind(&base::DoNothing))) | |
223 return gfx::Size(0, 0); | |
224 for (size_t i = 0; | |
225 supported_profiles_[i].profile != media::VIDEO_CODEC_PROFILE_UNKNOWN; | |
226 ++i) { | |
227 if (supported_profiles_[i].profile == profile && | |
228 supported_profiles_[i].mode == mode) | |
229 return supported_profiles_[i].max_resolution; | |
230 } | |
231 return gfx::Size(0, 0); | |
232 } | |
233 | |
204 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { | 234 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
205 base::AutoLock auto_lock(va_lock_); | 235 base::AutoLock auto_lock(va_lock_); |
206 VADisplayAttribute item = {VADisplayAttribRenderMode, | 236 VADisplayAttribute item = {VADisplayAttribRenderMode, |
207 1, // At least support '_LOCAL_OVERLAY'. | 237 1, // At least support '_LOCAL_OVERLAY'. |
208 -1, // The maximum possible support 'ALL'. | 238 -1, // The maximum possible support 'ALL'. |
209 VA_RENDER_MODE_LOCAL_GPU, | 239 VA_RENDER_MODE_LOCAL_GPU, |
210 VA_DISPLAY_ATTRIB_SETTABLE}; | 240 VA_DISPLAY_ATTRIB_SETTABLE}; |
211 | 241 |
212 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 242 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
213 if (va_res != VA_STATUS_SUCCESS) | 243 if (va_res != VA_STATUS_SUCCESS) |
214 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 244 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
215 } | 245 } |
216 | 246 |
247 void VaapiWrapper::InitializeSupportedProfiles() { | |
248 if (is_initialize_profile_) | |
wuchengli
2015/02/03 03:17:33
Originally this class is thread-safe. You need |va
henryhsu
2015/02/13 04:01:03
Done.
| |
249 return; | |
250 std::vector<VAProfile> va_profiles; | |
251 if (!GetSupportedVaProfiles(&va_profiles)) | |
252 return; | |
253 | |
254 size_t num_profiles = 0; | |
255 std::vector<CodecMode> modes({kDecode, kEncode}); | |
256 for (size_t i = 0; i < arraysize(kProfileMap); i++) { | |
kcwu
2015/02/02 10:11:01
DCHECK_LT(arraysize(kProfileMap) * modes.size(), a
henryhsu
2015/02/13 04:01:03
Not used anymore
| |
257 VAProfile va_profile = kProfileMap[i].va_profile; | |
258 for (size_t j = 0; j < modes.size(); j++) { | |
259 std::vector<VAConfigAttrib> required_attribs = | |
260 GetRequiredAttribs(modes[j]); | |
261 VAEntrypoint entrypoint = | |
262 (modes[j] == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD); | |
263 if (GetSupportedVaProfile(va_profile, va_profiles) != VAProfileNone && | |
264 IsEntrypointSupported(va_profile, entrypoint) && | |
265 AreAttribsSupported(va_profile, entrypoint, required_attribs)) { | |
266 supported_profiles_[num_profiles].profile = kProfileMap[i].profile; | |
267 supported_profiles_[num_profiles].mode = modes[j]; | |
268 VAConfigID config_id; | |
269 VAStatus va_res = vaCreateConfig( | |
270 va_display_, | |
271 va_profile, | |
272 entrypoint, | |
273 &required_attribs[0], | |
274 required_attribs.size(), | |
275 &config_id); | |
276 if (va_res == VA_STATUS_SUCCESS) { | |
277 GetVaCodecMaxResolution(config_id, | |
kcwu
2015/02/02 10:11:02
didn't check return value?
henryhsu
2015/02/13 04:01:03
Done.
| |
278 &supported_profiles_[num_profiles].max_resolution); | |
279 num_profiles++; | |
280 } | |
281 } | |
282 } | |
283 } | |
284 supported_profiles_[num_profiles].profile = | |
285 media::VIDEO_CODEC_PROFILE_UNKNOWN; | |
286 is_initialize_profile_ = true; | |
287 } | |
288 | |
217 bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) { | 289 bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) { |
218 static bool vaapi_functions_initialized = PostSandboxInitialization(); | 290 static bool vaapi_functions_initialized = PostSandboxInitialization(); |
219 if (!vaapi_functions_initialized) { | 291 if (!vaapi_functions_initialized) { |
220 bool running_on_chromeos = false; | 292 bool running_on_chromeos = false; |
221 #if defined(OS_CHROMEOS) | 293 #if defined(OS_CHROMEOS) |
222 // When chrome runs on linux with chromeos=1, do not log error message | 294 // When chrome runs on linux with chromeos=1, do not log error message |
223 // without VAAPI libraries. | 295 // without VAAPI libraries. |
224 running_on_chromeos = base::SysInfo::IsRunningOnChromeOS(); | 296 running_on_chromeos = base::SysInfo::IsRunningOnChromeOS(); |
225 #endif | 297 #endif |
226 static const char kErrorMsg[] = "Failed to initialize VAAPI libs"; | 298 static const char kErrorMsg[] = "Failed to initialize VAAPI libs"; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
331 (attribs[i].value & required_attribs[i].value) != | 403 (attribs[i].value & required_attribs[i].value) != |
332 required_attribs[i].value) { | 404 required_attribs[i].value) { |
333 DVLOG(1) << "Unsupported value " << required_attribs[i].value | 405 DVLOG(1) << "Unsupported value " << required_attribs[i].value |
334 << " for attribute type " << required_attribs[i].type; | 406 << " for attribute type " << required_attribs[i].type; |
335 return false; | 407 return false; |
336 } | 408 } |
337 } | 409 } |
338 return true; | 410 return true; |
339 } | 411 } |
340 | 412 |
413 bool VaapiWrapper::GetVaCodecMaxResolution(VAConfigID config_id, | |
414 gfx::Size* resolution) { | |
415 base::AutoLock auto_lock(va_lock_); | |
416 unsigned int num_attribs; | |
417 VAStatus va_res; | |
418 | |
419 va_res = vaQuerySurfaceAttributes( | |
420 va_display_, config_id, NULL, &num_attribs); | |
421 VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false); | |
422 | |
423 std::vector<VASurfaceAttrib> attrib_list( | |
424 base::checked_cast<size_t>(num_attribs)); | |
425 | |
426 va_res = vaQuerySurfaceAttributes( | |
427 va_display_, 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 (size_t i = 0; i < num_attribs; i++) { | |
432 switch (attrib_list[i].type) { | |
433 case VASurfaceAttribMaxWidth: | |
434 resolution->set_width(attrib_list[i].value.value.i); | |
435 break; | |
436 case VASurfaceAttribMaxHeight: | |
437 resolution->set_height(attrib_list[i].value.value.i); | |
438 break; | |
439 default: | |
440 break; | |
441 } | |
442 } | |
443 return true; | |
kcwu
2015/02/02 10:11:02
Is it guaranteed that there are always VaSurfaceAt
henryhsu
2015/02/02 10:42:24
No. If attributes don't include MaxWidth and MaxHe
| |
444 } | |
445 | |
341 bool VaapiWrapper::Initialize(CodecMode mode, | 446 bool VaapiWrapper::Initialize(CodecMode mode, |
342 media::VideoCodecProfile profile, | 447 media::VideoCodecProfile profile) { |
343 const base::Closure& report_error_to_uma_cb) { | 448 std::vector<media::VideoCodecProfile> supported_profiles = |
344 if (!VaInitialize(report_error_to_uma_cb)) | 449 GetSupportedProfiles(mode); |
450 if (std::find(supported_profiles.begin(), | |
451 supported_profiles.end(), | |
452 profile) == supported_profiles.end()) { | |
453 DVLOG(1) << "Unsupported profile"; | |
345 return false; | 454 return false; |
346 std::vector<VAProfile> supported_va_profiles; | 455 } |
347 if (!GetSupportedVaProfiles(&supported_va_profiles)) | 456 |
348 return false; | 457 VAProfile va_profile = ProfileToVAProfile(profile); |
349 VAProfile va_profile = ProfileToVAProfile(profile, supported_va_profiles); | |
350 if (va_profile == VAProfileNone) { | 458 if (va_profile == VAProfileNone) { |
351 DVLOG(1) << "Unsupported profile"; | 459 DVLOG(1) << "Unsupported profile"; |
352 return false; | 460 return false; |
353 } | 461 } |
354 VAEntrypoint entrypoint = | |
355 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | |
356 if (!IsEntrypointSupported(va_profile, entrypoint)) | |
357 return false; | |
358 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | |
359 if (!AreAttribsSupported(va_profile, entrypoint, required_attribs)) | |
360 return false; | |
361 | 462 |
362 TryToSetVADisplayAttributeToLocalGPU(); | 463 TryToSetVADisplayAttributeToLocalGPU(); |
363 | 464 |
465 VAEntrypoint entrypoint = | |
466 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | |
467 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | |
364 base::AutoLock auto_lock(va_lock_); | 468 base::AutoLock auto_lock(va_lock_); |
365 VAStatus va_res = vaCreateConfig(va_display_, | 469 VAStatus va_res = vaCreateConfig(va_display_, |
366 va_profile, | 470 va_profile, |
367 entrypoint, | 471 entrypoint, |
368 &required_attribs[0], | 472 &required_attribs[0], |
369 required_attribs.size(), | 473 required_attribs.size(), |
370 &va_config_id_); | 474 &va_config_id_); |
371 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); | 475 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); |
372 | 476 |
373 return true; | 477 return true; |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
906 #if defined(USE_X11) | 1010 #if defined(USE_X11) |
907 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | 1011 paths[kModuleVa_x11].push_back("libva-x11.so.1"); |
908 #elif defined(USE_OZONE) | 1012 #elif defined(USE_OZONE) |
909 paths[kModuleVa_drm].push_back("libva-drm.so.1"); | 1013 paths[kModuleVa_drm].push_back("libva-drm.so.1"); |
910 #endif | 1014 #endif |
911 | 1015 |
912 return InitializeStubs(paths); | 1016 return InitializeStubs(paths); |
913 } | 1017 } |
914 | 1018 |
915 } // namespace content | 1019 } // namespace content |
OLD | NEW |