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

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

Issue 872623002: VaapiVEA: Get maximum resolution from libva (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: modify description Created 5 years, 10 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
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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« content/common/gpu/media/vaapi_wrapper.h ('K') | « 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