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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 return (ret); \ | 55 return (ret); \ |
56 } \ | 56 } \ |
57 } while (0) | 57 } while (0) |
58 | 58 |
59 namespace content { | 59 namespace content { |
60 | 60 |
61 // Maximum framerate of encoded profile. This value is an arbitary limit | 61 // Maximum framerate of encoded profile. This value is an arbitary limit |
62 // and not taken from HW documentation. | 62 // and not taken from HW documentation. |
63 const int kMaxEncoderFramerate = 30; | 63 const int kMaxEncoderFramerate = 30; |
64 | 64 |
| 65 base::LazyInstance<VaapiWrapper::VADisplayState> |
| 66 VaapiWrapper::va_display_state_ = LAZY_INSTANCE_INITIALIZER; |
| 67 |
65 base::LazyInstance<VaapiWrapper::LazyProfileInfos> | 68 base::LazyInstance<VaapiWrapper::LazyProfileInfos> |
66 VaapiWrapper::profile_infos_ = LAZY_INSTANCE_INITIALIZER; | 69 VaapiWrapper::profile_infos_ = LAZY_INSTANCE_INITIALIZER; |
67 | 70 |
68 // Config attributes common for both encode and decode. | 71 // Config attributes common for both encode and decode. |
69 static const VAConfigAttrib kCommonVAConfigAttribs[] = { | 72 static const VAConfigAttrib kCommonVAConfigAttribs[] = { |
70 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, | 73 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, |
71 }; | 74 }; |
72 | 75 |
73 // Attributes required for encode. | 76 // Attributes required for encode. |
74 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { | 77 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 } | 119 } |
117 | 120 |
118 VASurface::~VASurface() { | 121 VASurface::~VASurface() { |
119 release_cb_.Run(va_surface_id_); | 122 release_cb_.Run(va_surface_id_); |
120 } | 123 } |
121 | 124 |
122 VaapiWrapper::VaapiWrapper() | 125 VaapiWrapper::VaapiWrapper() |
123 : va_display_(NULL), | 126 : va_display_(NULL), |
124 va_config_id_(VA_INVALID_ID), | 127 va_config_id_(VA_INVALID_ID), |
125 va_context_id_(VA_INVALID_ID), | 128 va_context_id_(VA_INVALID_ID), |
126 va_initialized_(false), | |
127 va_vpp_config_id_(VA_INVALID_ID), | 129 va_vpp_config_id_(VA_INVALID_ID), |
128 va_vpp_context_id_(VA_INVALID_ID), | 130 va_vpp_context_id_(VA_INVALID_ID), |
129 va_vpp_buffer_id_(VA_INVALID_ID) { | 131 va_vpp_buffer_id_(VA_INVALID_ID) { |
| 132 va_lock_ = va_display_state_.Get().va_lock(); |
130 } | 133 } |
131 | 134 |
132 VaapiWrapper::~VaapiWrapper() { | 135 VaapiWrapper::~VaapiWrapper() { |
133 DestroyPendingBuffers(); | 136 DestroyPendingBuffers(); |
134 DestroyCodedBuffers(); | 137 DestroyCodedBuffers(); |
135 DestroySurfaces(); | 138 DestroySurfaces(); |
136 DeinitializeVpp(); | 139 DeinitializeVpp(); |
137 Deinitialize(); | 140 Deinitialize(); |
138 } | 141 } |
139 | 142 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 profile.min_resolution.SetSize(16, 16); | 219 profile.min_resolution.SetSize(16, 16); |
217 profiles.push_back(profile); | 220 profiles.push_back(profile); |
218 break; | 221 break; |
219 } | 222 } |
220 } | 223 } |
221 } | 224 } |
222 return profiles; | 225 return profiles; |
223 } | 226 } |
224 | 227 |
225 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { | 228 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
226 base::AutoLock auto_lock(va_lock_); | 229 base::AutoLock auto_lock(*va_lock_); |
227 VADisplayAttribute item = {VADisplayAttribRenderMode, | 230 VADisplayAttribute item = {VADisplayAttribRenderMode, |
228 1, // At least support '_LOCAL_OVERLAY'. | 231 1, // At least support '_LOCAL_OVERLAY'. |
229 -1, // The maximum possible support 'ALL'. | 232 -1, // The maximum possible support 'ALL'. |
230 VA_RENDER_MODE_LOCAL_GPU, | 233 VA_RENDER_MODE_LOCAL_GPU, |
231 VA_DISPLAY_ATTRIB_SETTABLE}; | 234 VA_DISPLAY_ATTRIB_SETTABLE}; |
232 | 235 |
233 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 236 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
234 if (va_res != VA_STATUS_SUCCESS) | 237 if (va_res != VA_STATUS_SUCCESS) |
235 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 238 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
236 } | 239 } |
(...skipping 28 matching lines...) Expand all Loading... |
265 VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) { | 268 VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) { |
266 std::vector<ProfileInfo> supported_profile_infos; | 269 std::vector<ProfileInfo> supported_profile_infos; |
267 std::vector<VAProfile> va_profiles; | 270 std::vector<VAProfile> va_profiles; |
268 if (!GetSupportedVaProfiles(&va_profiles)) | 271 if (!GetSupportedVaProfiles(&va_profiles)) |
269 return supported_profile_infos; | 272 return supported_profile_infos; |
270 | 273 |
271 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | 274 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); |
272 VAEntrypoint entrypoint = | 275 VAEntrypoint entrypoint = |
273 (mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD); | 276 (mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD); |
274 | 277 |
275 base::AutoLock auto_lock(va_lock_); | 278 base::AutoLock auto_lock(*va_lock_); |
276 for (const auto& va_profile : va_profiles) { | 279 for (const auto& va_profile : va_profiles) { |
277 if (!IsEntrypointSupported_Locked(va_profile, entrypoint)) | 280 if (!IsEntrypointSupported_Locked(va_profile, entrypoint)) |
278 continue; | 281 continue; |
279 if (!AreAttribsSupported_Locked(va_profile, entrypoint, required_attribs)) | 282 if (!AreAttribsSupported_Locked(va_profile, entrypoint, required_attribs)) |
280 continue; | 283 continue; |
281 ProfileInfo profile_info; | 284 ProfileInfo profile_info; |
282 if (!GetMaxResolution_Locked(va_profile, | 285 if (!GetMaxResolution_Locked(va_profile, |
283 entrypoint, | 286 entrypoint, |
284 required_attribs, | 287 required_attribs, |
285 &profile_info.max_resolution)) { | 288 &profile_info.max_resolution)) { |
(...skipping 19 matching lines...) Expand all Loading... |
305 static const char kErrorMsg[] = "Failed to initialize VAAPI libs"; | 308 static const char kErrorMsg[] = "Failed to initialize VAAPI libs"; |
306 if (running_on_chromeos) | 309 if (running_on_chromeos) |
307 LOG(ERROR) << kErrorMsg; | 310 LOG(ERROR) << kErrorMsg; |
308 else | 311 else |
309 DVLOG(1) << kErrorMsg; | 312 DVLOG(1) << kErrorMsg; |
310 return false; | 313 return false; |
311 } | 314 } |
312 | 315 |
313 report_error_to_uma_cb_ = report_error_to_uma_cb; | 316 report_error_to_uma_cb_ = report_error_to_uma_cb; |
314 | 317 |
315 base::AutoLock auto_lock(va_lock_); | 318 base::AutoLock auto_lock(*va_lock_); |
316 | 319 |
317 #if defined(USE_X11) | 320 VADisplayState* va_display_state = &va_display_state_.Get(); |
318 va_display_ = vaGetDisplay(gfx::GetXDisplay()); | 321 if (!va_display_state) { |
319 #elif defined(USE_OZONE) | 322 LOG(ERROR) << "Failed to allocate VA display state"; |
320 const char* kDriRenderNode0Path = "/dev/dri/renderD128"; | |
321 drm_file_ = base::File(base::FilePath::FromUTF8Unsafe(kDriRenderNode0Path), | |
322 base::File::FLAG_OPEN | base::File::FLAG_READ | | |
323 base::File::FLAG_WRITE); | |
324 va_display_ = vaGetDisplayDRM(drm_file_.GetPlatformFile()); | |
325 #endif // USE_X11 | |
326 | |
327 if (!vaDisplayIsValid(va_display_)) { | |
328 LOG(ERROR) << "Could not get a valid VA display"; | |
329 return false; | 323 return false; |
330 } | 324 } |
331 | 325 |
332 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); | 326 VAStatus va_res = VA_STATUS_SUCCESS; |
333 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); | 327 if (!va_display_state->Initialize(&va_res)) { |
334 va_initialized_ = true; | 328 VA_LOG_ON_ERROR(va_res, "vaInitialize failed"); |
335 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; | |
336 | |
337 if (VAAPIVersionLessThan(0, 34)) { | |
338 LOG(ERROR) << "VAAPI version < 0.34 is not supported."; | |
339 return false; | 329 return false; |
340 } | 330 } |
| 331 |
| 332 va_display_ = va_display_state->va_display(); |
341 return true; | 333 return true; |
342 } | 334 } |
343 | 335 |
344 bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) { | 336 bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) { |
345 base::AutoLock auto_lock(va_lock_); | 337 base::AutoLock auto_lock(*va_lock_); |
346 // Query the driver for supported profiles. | 338 // Query the driver for supported profiles. |
347 int max_profiles = vaMaxNumProfiles(va_display_); | 339 int max_profiles = vaMaxNumProfiles(va_display_); |
348 std::vector<VAProfile> supported_profiles( | 340 std::vector<VAProfile> supported_profiles( |
349 base::checked_cast<size_t>(max_profiles)); | 341 base::checked_cast<size_t>(max_profiles)); |
350 | 342 |
351 int num_supported_profiles; | 343 int num_supported_profiles; |
352 VAStatus va_res = vaQueryConfigProfiles( | 344 VAStatus va_res = vaQueryConfigProfiles( |
353 va_display_, &supported_profiles[0], &num_supported_profiles); | 345 va_display_, &supported_profiles[0], &num_supported_profiles); |
354 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); | 346 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); |
355 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { | 347 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { |
356 LOG(ERROR) << "vaQueryConfigProfiles returned: " << num_supported_profiles; | 348 LOG(ERROR) << "vaQueryConfigProfiles returned: " << num_supported_profiles; |
357 return false; | 349 return false; |
358 } | 350 } |
359 | 351 |
360 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); | 352 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); |
361 *profiles = supported_profiles; | 353 *profiles = supported_profiles; |
362 return true; | 354 return true; |
363 } | 355 } |
364 | 356 |
365 bool VaapiWrapper::IsEntrypointSupported_Locked(VAProfile va_profile, | 357 bool VaapiWrapper::IsEntrypointSupported_Locked(VAProfile va_profile, |
366 VAEntrypoint entrypoint) { | 358 VAEntrypoint entrypoint) { |
367 va_lock_.AssertAcquired(); | 359 va_lock_->AssertAcquired(); |
368 // Query the driver for supported entrypoints. | 360 // Query the driver for supported entrypoints. |
369 int max_entrypoints = vaMaxNumEntrypoints(va_display_); | 361 int max_entrypoints = vaMaxNumEntrypoints(va_display_); |
370 std::vector<VAEntrypoint> supported_entrypoints( | 362 std::vector<VAEntrypoint> supported_entrypoints( |
371 base::checked_cast<size_t>(max_entrypoints)); | 363 base::checked_cast<size_t>(max_entrypoints)); |
372 | 364 |
373 int num_supported_entrypoints; | 365 int num_supported_entrypoints; |
374 VAStatus va_res = vaQueryConfigEntrypoints(va_display_, | 366 VAStatus va_res = vaQueryConfigEntrypoints(va_display_, |
375 va_profile, | 367 va_profile, |
376 &supported_entrypoints[0], | 368 &supported_entrypoints[0], |
377 &num_supported_entrypoints); | 369 &num_supported_entrypoints); |
(...skipping 11 matching lines...) Expand all Loading... |
389 DVLOG(1) << "Unsupported entrypoint"; | 381 DVLOG(1) << "Unsupported entrypoint"; |
390 return false; | 382 return false; |
391 } | 383 } |
392 return true; | 384 return true; |
393 } | 385 } |
394 | 386 |
395 bool VaapiWrapper::AreAttribsSupported_Locked( | 387 bool VaapiWrapper::AreAttribsSupported_Locked( |
396 VAProfile va_profile, | 388 VAProfile va_profile, |
397 VAEntrypoint entrypoint, | 389 VAEntrypoint entrypoint, |
398 const std::vector<VAConfigAttrib>& required_attribs) { | 390 const std::vector<VAConfigAttrib>& required_attribs) { |
399 va_lock_.AssertAcquired(); | 391 va_lock_->AssertAcquired(); |
400 // Query the driver for required attributes. | 392 // Query the driver for required attributes. |
401 std::vector<VAConfigAttrib> attribs = required_attribs; | 393 std::vector<VAConfigAttrib> attribs = required_attribs; |
402 for (size_t i = 0; i < required_attribs.size(); ++i) | 394 for (size_t i = 0; i < required_attribs.size(); ++i) |
403 attribs[i].value = 0; | 395 attribs[i].value = 0; |
404 | 396 |
405 VAStatus va_res = vaGetConfigAttributes( | 397 VAStatus va_res = vaGetConfigAttributes( |
406 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); | 398 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); |
407 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); | 399 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); |
408 | 400 |
409 for (size_t i = 0; i < required_attribs.size(); ++i) { | 401 for (size_t i = 0; i < required_attribs.size(); ++i) { |
410 if (attribs[i].type != required_attribs[i].type || | 402 if (attribs[i].type != required_attribs[i].type || |
411 (attribs[i].value & required_attribs[i].value) != | 403 (attribs[i].value & required_attribs[i].value) != |
412 required_attribs[i].value) { | 404 required_attribs[i].value) { |
413 DVLOG(1) << "Unsupported value " << required_attribs[i].value | 405 DVLOG(1) << "Unsupported value " << required_attribs[i].value |
414 << " for attribute type " << required_attribs[i].type; | 406 << " for attribute type " << required_attribs[i].type; |
415 return false; | 407 return false; |
416 } | 408 } |
417 } | 409 } |
418 return true; | 410 return true; |
419 } | 411 } |
420 | 412 |
421 bool VaapiWrapper::GetMaxResolution_Locked( | 413 bool VaapiWrapper::GetMaxResolution_Locked( |
422 VAProfile va_profile, | 414 VAProfile va_profile, |
423 VAEntrypoint entrypoint, | 415 VAEntrypoint entrypoint, |
424 std::vector<VAConfigAttrib>& required_attribs, | 416 std::vector<VAConfigAttrib>& required_attribs, |
425 gfx::Size* resolution) { | 417 gfx::Size* resolution) { |
426 va_lock_.AssertAcquired(); | 418 va_lock_->AssertAcquired(); |
427 VAConfigID va_config_id; | 419 VAConfigID va_config_id; |
428 VAStatus va_res = vaCreateConfig( | 420 VAStatus va_res = vaCreateConfig( |
429 va_display_, | 421 va_display_, |
430 va_profile, | 422 va_profile, |
431 entrypoint, | 423 entrypoint, |
432 &required_attribs[0], | 424 &required_attribs[0], |
433 required_attribs.size(), | 425 required_attribs.size(), |
434 &va_config_id); | 426 &va_config_id); |
435 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); | 427 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); |
436 | 428 |
(...skipping 28 matching lines...) Expand all Loading... |
465 } | 457 } |
466 return true; | 458 return true; |
467 } | 459 } |
468 | 460 |
469 bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { | 461 bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { |
470 TryToSetVADisplayAttributeToLocalGPU(); | 462 TryToSetVADisplayAttributeToLocalGPU(); |
471 | 463 |
472 VAEntrypoint entrypoint = | 464 VAEntrypoint entrypoint = |
473 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | 465 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); |
474 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | 466 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); |
475 base::AutoLock auto_lock(va_lock_); | 467 base::AutoLock auto_lock(*va_lock_); |
476 VAStatus va_res = vaCreateConfig(va_display_, | 468 VAStatus va_res = vaCreateConfig(va_display_, |
477 va_profile, | 469 va_profile, |
478 entrypoint, | 470 entrypoint, |
479 &required_attribs[0], | 471 &required_attribs[0], |
480 required_attribs.size(), | 472 required_attribs.size(), |
481 &va_config_id_); | 473 &va_config_id_); |
482 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); | 474 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); |
483 | 475 |
484 return true; | 476 return true; |
485 } | 477 } |
486 | 478 |
487 void VaapiWrapper::Deinitialize() { | 479 void VaapiWrapper::Deinitialize() { |
488 base::AutoLock auto_lock(va_lock_); | 480 base::AutoLock auto_lock(*va_lock_); |
489 | 481 |
490 if (va_config_id_ != VA_INVALID_ID) { | 482 if (va_config_id_ != VA_INVALID_ID) { |
491 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); | 483 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); |
492 VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); | 484 VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); |
493 } | 485 } |
494 | 486 |
495 // Must check if vaInitialize completed successfully, to work around a bug in | 487 VADisplayState* va_display_state = &va_display_state_.Get(); |
496 // libva. The bug was fixed upstream: | 488 if (va_display_state) { |
497 // http://lists.freedesktop.org/archives/libva/2013-July/001807.html | 489 VAStatus va_res = VA_STATUS_SUCCESS; |
498 // TODO(mgiuca): Remove this check, and the |va_initialized_| variable, once | 490 va_display_state->Deinitialize(&va_res); |
499 // the fix has rolled out sufficiently. | |
500 if (va_initialized_ && va_display_) { | |
501 VAStatus va_res = vaTerminate(va_display_); | |
502 VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); | 491 VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); |
503 } | 492 } |
504 | 493 |
505 va_config_id_ = VA_INVALID_ID; | 494 va_config_id_ = VA_INVALID_ID; |
506 va_display_ = NULL; | 495 va_display_ = NULL; |
507 va_initialized_ = false; | |
508 } | |
509 | |
510 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { | |
511 return (major_version_ < major) || | |
512 (major_version_ == major && minor_version_ < minor); | |
513 } | 496 } |
514 | 497 |
515 bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, | 498 bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, |
516 size_t num_surfaces, | 499 size_t num_surfaces, |
517 std::vector<VASurfaceID>* va_surfaces) { | 500 std::vector<VASurfaceID>* va_surfaces) { |
518 base::AutoLock auto_lock(va_lock_); | 501 base::AutoLock auto_lock(*va_lock_); |
519 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; | 502 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; |
520 | 503 |
521 DCHECK(va_surfaces->empty()); | 504 DCHECK(va_surfaces->empty()); |
522 DCHECK(va_surface_ids_.empty()); | 505 DCHECK(va_surface_ids_.empty()); |
523 va_surface_ids_.resize(num_surfaces); | 506 va_surface_ids_.resize(num_surfaces); |
524 | 507 |
525 // Allocate surfaces in driver. | 508 // Allocate surfaces in driver. |
526 VAStatus va_res = vaCreateSurfaces(va_display_, | 509 VAStatus va_res = vaCreateSurfaces(va_display_, |
527 VA_RT_FORMAT_YUV420, | 510 VA_RT_FORMAT_YUV420, |
528 size.width(), size.height(), | 511 size.width(), size.height(), |
(...skipping 17 matching lines...) Expand all Loading... |
546 if (va_res != VA_STATUS_SUCCESS) { | 529 if (va_res != VA_STATUS_SUCCESS) { |
547 DestroySurfaces(); | 530 DestroySurfaces(); |
548 return false; | 531 return false; |
549 } | 532 } |
550 | 533 |
551 *va_surfaces = va_surface_ids_; | 534 *va_surfaces = va_surface_ids_; |
552 return true; | 535 return true; |
553 } | 536 } |
554 | 537 |
555 void VaapiWrapper::DestroySurfaces() { | 538 void VaapiWrapper::DestroySurfaces() { |
556 base::AutoLock auto_lock(va_lock_); | 539 base::AutoLock auto_lock(*va_lock_); |
557 DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces"; | 540 DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces"; |
558 | 541 |
559 if (va_context_id_ != VA_INVALID_ID) { | 542 if (va_context_id_ != VA_INVALID_ID) { |
560 VAStatus va_res = vaDestroyContext(va_display_, va_context_id_); | 543 VAStatus va_res = vaDestroyContext(va_display_, va_context_id_); |
561 VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed"); | 544 VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed"); |
562 } | 545 } |
563 | 546 |
564 if (!va_surface_ids_.empty()) { | 547 if (!va_surface_ids_.empty()) { |
565 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_ids_[0], | 548 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_ids_[0], |
566 va_surface_ids_.size()); | 549 va_surface_ids_.size()); |
567 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed"); | 550 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed"); |
568 } | 551 } |
569 | 552 |
570 va_surface_ids_.clear(); | 553 va_surface_ids_.clear(); |
571 va_context_id_ = VA_INVALID_ID; | 554 va_context_id_ = VA_INVALID_ID; |
572 } | 555 } |
573 | 556 |
574 scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface( | 557 scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface( |
575 unsigned int va_format, | 558 unsigned int va_format, |
576 const gfx::Size& size, | 559 const gfx::Size& size, |
577 const std::vector<VASurfaceAttrib>& va_attribs) { | 560 const std::vector<VASurfaceAttrib>& va_attribs) { |
578 base::AutoLock auto_lock(va_lock_); | 561 base::AutoLock auto_lock(*va_lock_); |
579 | 562 |
580 std::vector<VASurfaceAttrib> attribs(va_attribs); | 563 std::vector<VASurfaceAttrib> attribs(va_attribs); |
581 VASurfaceID va_surface_id; | 564 VASurfaceID va_surface_id; |
582 VAStatus va_res = | 565 VAStatus va_res = |
583 vaCreateSurfaces(va_display_, va_format, size.width(), size.height(), | 566 vaCreateSurfaces(va_display_, va_format, size.width(), size.height(), |
584 &va_surface_id, 1, &attribs[0], attribs.size()); | 567 &va_surface_id, 1, &attribs[0], attribs.size()); |
585 | 568 |
586 scoped_refptr<VASurface> va_surface; | 569 scoped_refptr<VASurface> va_surface; |
587 VA_SUCCESS_OR_RETURN(va_res, "Failed to create unowned VASurface", | 570 VA_SUCCESS_OR_RETURN(va_res, "Failed to create unowned VASurface", |
588 va_surface); | 571 va_surface); |
589 | 572 |
590 // This is safe to use Unretained() here, because the VDA takes care | 573 // This is safe to use Unretained() here, because the VDA takes care |
591 // of the destruction order. All the surfaces will be destroyed | 574 // of the destruction order. All the surfaces will be destroyed |
592 // before VaapiWrapper. | 575 // before VaapiWrapper. |
593 va_surface = new VASurface( | 576 va_surface = new VASurface( |
594 va_surface_id, size, | 577 va_surface_id, size, |
595 base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this))); | 578 base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this))); |
596 | 579 |
597 return va_surface; | 580 return va_surface; |
598 } | 581 } |
599 | 582 |
600 void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) { | 583 void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) { |
601 base::AutoLock auto_lock(va_lock_); | 584 base::AutoLock auto_lock(*va_lock_); |
602 | 585 |
603 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1); | 586 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1); |
604 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed"); | 587 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed"); |
605 } | 588 } |
606 | 589 |
607 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, | 590 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, |
608 size_t size, | 591 size_t size, |
609 void* buffer) { | 592 void* buffer) { |
610 base::AutoLock auto_lock(va_lock_); | 593 base::AutoLock auto_lock(*va_lock_); |
611 | 594 |
612 VABufferID buffer_id; | 595 VABufferID buffer_id; |
613 VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, | 596 VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, |
614 va_buffer_type, size, | 597 va_buffer_type, size, |
615 1, buffer, &buffer_id); | 598 1, buffer, &buffer_id); |
616 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); | 599 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); |
617 | 600 |
618 switch (va_buffer_type) { | 601 switch (va_buffer_type) { |
619 case VASliceParameterBufferType: | 602 case VASliceParameterBufferType: |
620 case VASliceDataBufferType: | 603 case VASliceDataBufferType: |
621 case VAEncSliceParameterBufferType: | 604 case VAEncSliceParameterBufferType: |
622 pending_slice_bufs_.push_back(buffer_id); | 605 pending_slice_bufs_.push_back(buffer_id); |
623 break; | 606 break; |
624 | 607 |
625 default: | 608 default: |
626 pending_va_bufs_.push_back(buffer_id); | 609 pending_va_bufs_.push_back(buffer_id); |
627 break; | 610 break; |
628 } | 611 } |
629 | 612 |
630 return true; | 613 return true; |
631 } | 614 } |
632 | 615 |
633 bool VaapiWrapper::SubmitVAEncMiscParamBuffer( | 616 bool VaapiWrapper::SubmitVAEncMiscParamBuffer( |
634 VAEncMiscParameterType misc_param_type, | 617 VAEncMiscParameterType misc_param_type, |
635 size_t size, | 618 size_t size, |
636 void* buffer) { | 619 void* buffer) { |
637 base::AutoLock auto_lock(va_lock_); | 620 base::AutoLock auto_lock(*va_lock_); |
638 | 621 |
639 VABufferID buffer_id; | 622 VABufferID buffer_id; |
640 VAStatus va_res = vaCreateBuffer(va_display_, | 623 VAStatus va_res = vaCreateBuffer(va_display_, |
641 va_context_id_, | 624 va_context_id_, |
642 VAEncMiscParameterBufferType, | 625 VAEncMiscParameterBufferType, |
643 sizeof(VAEncMiscParameterBuffer) + size, | 626 sizeof(VAEncMiscParameterBuffer) + size, |
644 1, | 627 1, |
645 NULL, | 628 NULL, |
646 &buffer_id); | 629 &buffer_id); |
647 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); | 630 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); |
(...skipping 13 matching lines...) Expand all Loading... |
661 misc_param->type = misc_param_type; | 644 misc_param->type = misc_param_type; |
662 memcpy(misc_param->data, buffer, size); | 645 memcpy(misc_param->data, buffer, size); |
663 va_res = vaUnmapBuffer(va_display_, buffer_id); | 646 va_res = vaUnmapBuffer(va_display_, buffer_id); |
664 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 647 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
665 | 648 |
666 pending_va_bufs_.push_back(buffer_id); | 649 pending_va_bufs_.push_back(buffer_id); |
667 return true; | 650 return true; |
668 } | 651 } |
669 | 652 |
670 void VaapiWrapper::DestroyPendingBuffers() { | 653 void VaapiWrapper::DestroyPendingBuffers() { |
671 base::AutoLock auto_lock(va_lock_); | 654 base::AutoLock auto_lock(*va_lock_); |
672 | 655 |
673 for (const auto& pending_va_buf : pending_va_bufs_) { | 656 for (const auto& pending_va_buf : pending_va_bufs_) { |
674 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_buf); | 657 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_buf); |
675 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 658 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
676 } | 659 } |
677 | 660 |
678 for (const auto& pending_slice_buf : pending_slice_bufs_) { | 661 for (const auto& pending_slice_buf : pending_slice_bufs_) { |
679 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_buf); | 662 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_buf); |
680 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 663 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
681 } | 664 } |
682 | 665 |
683 pending_va_bufs_.clear(); | 666 pending_va_bufs_.clear(); |
684 pending_slice_bufs_.clear(); | 667 pending_slice_bufs_.clear(); |
685 } | 668 } |
686 | 669 |
687 bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { | 670 bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { |
688 base::AutoLock auto_lock(va_lock_); | 671 base::AutoLock auto_lock(*va_lock_); |
689 VAStatus va_res = vaCreateBuffer(va_display_, | 672 VAStatus va_res = vaCreateBuffer(va_display_, |
690 va_context_id_, | 673 va_context_id_, |
691 VAEncCodedBufferType, | 674 VAEncCodedBufferType, |
692 size, | 675 size, |
693 1, | 676 1, |
694 NULL, | 677 NULL, |
695 buffer_id); | 678 buffer_id); |
696 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a coded buffer", false); | 679 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a coded buffer", false); |
697 | 680 |
698 DCHECK(coded_buffers_.insert(*buffer_id).second); | 681 DCHECK(coded_buffers_.insert(*buffer_id).second); |
699 return true; | 682 return true; |
700 } | 683 } |
701 | 684 |
702 void VaapiWrapper::DestroyCodedBuffers() { | 685 void VaapiWrapper::DestroyCodedBuffers() { |
703 base::AutoLock auto_lock(va_lock_); | 686 base::AutoLock auto_lock(*va_lock_); |
704 | 687 |
705 for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin(); | 688 for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin(); |
706 iter != coded_buffers_.end(); | 689 iter != coded_buffers_.end(); |
707 ++iter) { | 690 ++iter) { |
708 VAStatus va_res = vaDestroyBuffer(va_display_, *iter); | 691 VAStatus va_res = vaDestroyBuffer(va_display_, *iter); |
709 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 692 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
710 } | 693 } |
711 | 694 |
712 coded_buffers_.clear(); | 695 coded_buffers_.clear(); |
713 } | 696 } |
714 | 697 |
715 bool VaapiWrapper::Execute(VASurfaceID va_surface_id) { | 698 bool VaapiWrapper::Execute(VASurfaceID va_surface_id) { |
716 base::AutoLock auto_lock(va_lock_); | 699 base::AutoLock auto_lock(*va_lock_); |
717 | 700 |
718 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); | 701 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); |
719 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); | 702 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); |
720 DVLOG(4) << "Target VA surface " << va_surface_id; | 703 DVLOG(4) << "Target VA surface " << va_surface_id; |
721 | 704 |
722 // Get ready to execute for given surface. | 705 // Get ready to execute for given surface. |
723 VAStatus va_res = vaBeginPicture(va_display_, va_context_id_, | 706 VAStatus va_res = vaBeginPicture(va_display_, va_context_id_, |
724 va_surface_id); | 707 va_surface_id); |
725 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false); | 708 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false); |
726 | 709 |
(...skipping 25 matching lines...) Expand all Loading... |
752 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { | 735 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { |
753 bool result = Execute(va_surface_id); | 736 bool result = Execute(va_surface_id); |
754 DestroyPendingBuffers(); | 737 DestroyPendingBuffers(); |
755 return result; | 738 return result; |
756 } | 739 } |
757 | 740 |
758 #if defined(USE_X11) | 741 #if defined(USE_X11) |
759 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, | 742 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, |
760 Pixmap x_pixmap, | 743 Pixmap x_pixmap, |
761 gfx::Size dest_size) { | 744 gfx::Size dest_size) { |
762 base::AutoLock auto_lock(va_lock_); | 745 base::AutoLock auto_lock(*va_lock_); |
763 | 746 |
764 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 747 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
765 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 748 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
766 | 749 |
767 // Put the data into an X Pixmap. | 750 // Put the data into an X Pixmap. |
768 va_res = vaPutSurface(va_display_, | 751 va_res = vaPutSurface(va_display_, |
769 va_surface_id, | 752 va_surface_id, |
770 x_pixmap, | 753 x_pixmap, |
771 0, 0, dest_size.width(), dest_size.height(), | 754 0, 0, dest_size.width(), dest_size.height(), |
772 0, 0, dest_size.width(), dest_size.height(), | 755 0, 0, dest_size.width(), dest_size.height(), |
773 NULL, 0, 0); | 756 NULL, 0, 0); |
774 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); | 757 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); |
775 return true; | 758 return true; |
776 } | 759 } |
777 #endif // USE_X11 | 760 #endif // USE_X11 |
778 | 761 |
779 bool VaapiWrapper::GetDerivedVaImage(VASurfaceID va_surface_id, | 762 bool VaapiWrapper::GetDerivedVaImage(VASurfaceID va_surface_id, |
780 VAImage* image, | 763 VAImage* image, |
781 void** mem) { | 764 void** mem) { |
782 base::AutoLock auto_lock(va_lock_); | 765 base::AutoLock auto_lock(*va_lock_); |
783 | 766 |
784 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 767 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
785 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 768 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
786 | 769 |
787 // Derive a VAImage from the VASurface | 770 // Derive a VAImage from the VASurface |
788 va_res = vaDeriveImage(va_display_, va_surface_id, image); | 771 va_res = vaDeriveImage(va_display_, va_surface_id, image); |
789 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); | 772 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); |
790 if (va_res != VA_STATUS_SUCCESS) | 773 if (va_res != VA_STATUS_SUCCESS) |
791 return false; | 774 return false; |
792 | 775 |
793 // Map the VAImage into memory | 776 // Map the VAImage into memory |
794 va_res = vaMapBuffer(va_display_, image->buf, mem); | 777 va_res = vaMapBuffer(va_display_, image->buf, mem); |
795 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); | 778 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); |
796 if (va_res == VA_STATUS_SUCCESS) | 779 if (va_res == VA_STATUS_SUCCESS) |
797 return true; | 780 return true; |
798 | 781 |
799 va_res = vaDestroyImage(va_display_, image->image_id); | 782 va_res = vaDestroyImage(va_display_, image->image_id); |
800 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); | 783 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); |
801 | 784 |
802 return false; | 785 return false; |
803 } | 786 } |
804 | 787 |
805 bool VaapiWrapper::GetVaImage(VASurfaceID va_surface_id, | 788 bool VaapiWrapper::GetVaImage(VASurfaceID va_surface_id, |
806 VAImageFormat* format, | 789 VAImageFormat* format, |
807 const gfx::Size& size, | 790 const gfx::Size& size, |
808 VAImage* image, | 791 VAImage* image, |
809 void** mem) { | 792 void** mem) { |
810 base::AutoLock auto_lock(va_lock_); | 793 base::AutoLock auto_lock(*va_lock_); |
811 | 794 |
812 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 795 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
813 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 796 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
814 | 797 |
815 va_res = | 798 va_res = |
816 vaCreateImage(va_display_, format, size.width(), size.height(), image); | 799 vaCreateImage(va_display_, format, size.width(), size.height(), image); |
817 VA_SUCCESS_OR_RETURN(va_res, "vaCreateImage failed", false); | 800 VA_SUCCESS_OR_RETURN(va_res, "vaCreateImage failed", false); |
818 | 801 |
819 va_res = vaGetImage(va_display_, va_surface_id, 0, 0, size.width(), | 802 va_res = vaGetImage(va_display_, va_surface_id, 0, 0, size.width(), |
820 size.height(), image->image_id); | 803 size.height(), image->image_id); |
821 VA_LOG_ON_ERROR(va_res, "vaGetImage failed"); | 804 VA_LOG_ON_ERROR(va_res, "vaGetImage failed"); |
822 | 805 |
823 if (va_res == VA_STATUS_SUCCESS) { | 806 if (va_res == VA_STATUS_SUCCESS) { |
824 // Map the VAImage into memory | 807 // Map the VAImage into memory |
825 va_res = vaMapBuffer(va_display_, image->buf, mem); | 808 va_res = vaMapBuffer(va_display_, image->buf, mem); |
826 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); | 809 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); |
827 } | 810 } |
828 | 811 |
829 if (va_res != VA_STATUS_SUCCESS) { | 812 if (va_res != VA_STATUS_SUCCESS) { |
830 va_res = vaDestroyImage(va_display_, image->image_id); | 813 va_res = vaDestroyImage(va_display_, image->image_id); |
831 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); | 814 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); |
832 return false; | 815 return false; |
833 } | 816 } |
834 | 817 |
835 return true; | 818 return true; |
836 } | 819 } |
837 | 820 |
838 void VaapiWrapper::ReturnVaImage(VAImage* image) { | 821 void VaapiWrapper::ReturnVaImage(VAImage* image) { |
839 base::AutoLock auto_lock(va_lock_); | 822 base::AutoLock auto_lock(*va_lock_); |
840 | 823 |
841 VAStatus va_res = vaUnmapBuffer(va_display_, image->buf); | 824 VAStatus va_res = vaUnmapBuffer(va_display_, image->buf); |
842 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 825 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
843 | 826 |
844 va_res = vaDestroyImage(va_display_, image->image_id); | 827 va_res = vaDestroyImage(va_display_, image->image_id); |
845 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); | 828 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); |
846 } | 829 } |
847 | 830 |
848 static void DestroyVAImage(VADisplay va_display, VAImage image) { | 831 static void DestroyVAImage(VADisplay va_display, VAImage image) { |
849 if (image.image_id != VA_INVALID_ID) | 832 if (image.image_id != VA_INVALID_ID) |
850 vaDestroyImage(va_display, image.image_id); | 833 vaDestroyImage(va_display, image.image_id); |
851 } | 834 } |
852 | 835 |
853 bool VaapiWrapper::UploadVideoFrameToSurface( | 836 bool VaapiWrapper::UploadVideoFrameToSurface( |
854 const scoped_refptr<media::VideoFrame>& frame, | 837 const scoped_refptr<media::VideoFrame>& frame, |
855 VASurfaceID va_surface_id) { | 838 VASurfaceID va_surface_id) { |
856 base::AutoLock auto_lock(va_lock_); | 839 base::AutoLock auto_lock(*va_lock_); |
857 | 840 |
858 VAImage image; | 841 VAImage image; |
859 VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image); | 842 VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image); |
860 VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false); | 843 VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false); |
861 base::ScopedClosureRunner vaimage_deleter( | 844 base::ScopedClosureRunner vaimage_deleter( |
862 base::Bind(&DestroyVAImage, va_display_, image)); | 845 base::Bind(&DestroyVAImage, va_display_, image)); |
863 | 846 |
864 if (image.format.fourcc != VA_FOURCC_NV12) { | 847 if (image.format.fourcc != VA_FOURCC_NV12) { |
865 LOG(ERROR) << "Unsupported image format: " << image.format.fourcc; | 848 LOG(ERROR) << "Unsupported image format: " << image.format.fourcc; |
866 return false; | 849 return false; |
867 } | 850 } |
868 | 851 |
869 if (gfx::Rect(image.width, image.height) < gfx::Rect(frame->coded_size())) { | 852 if (gfx::Rect(image.width, image.height) < gfx::Rect(frame->coded_size())) { |
870 LOG(ERROR) << "Buffer too small to fit the frame."; | 853 LOG(ERROR) << "Buffer too small to fit the frame."; |
871 return false; | 854 return false; |
872 } | 855 } |
873 | 856 |
874 void* image_ptr = NULL; | 857 void* image_ptr = NULL; |
875 va_res = vaMapBuffer(va_display_, image.buf, &image_ptr); | 858 va_res = vaMapBuffer(va_display_, image.buf, &image_ptr); |
876 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); | 859 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); |
877 DCHECK(image_ptr); | 860 DCHECK(image_ptr); |
878 | 861 |
879 int ret = 0; | 862 int ret = 0; |
880 { | 863 { |
881 base::AutoUnlock auto_unlock(va_lock_); | 864 base::AutoUnlock auto_unlock(*va_lock_); |
882 ret = libyuv::I420ToNV12(frame->data(media::VideoFrame::kYPlane), | 865 ret = libyuv::I420ToNV12(frame->data(media::VideoFrame::kYPlane), |
883 frame->stride(media::VideoFrame::kYPlane), | 866 frame->stride(media::VideoFrame::kYPlane), |
884 frame->data(media::VideoFrame::kUPlane), | 867 frame->data(media::VideoFrame::kUPlane), |
885 frame->stride(media::VideoFrame::kUPlane), | 868 frame->stride(media::VideoFrame::kUPlane), |
886 frame->data(media::VideoFrame::kVPlane), | 869 frame->data(media::VideoFrame::kVPlane), |
887 frame->stride(media::VideoFrame::kVPlane), | 870 frame->stride(media::VideoFrame::kVPlane), |
888 static_cast<uint8*>(image_ptr) + image.offsets[0], | 871 static_cast<uint8*>(image_ptr) + image.offsets[0], |
889 image.pitches[0], | 872 image.pitches[0], |
890 static_cast<uint8*>(image_ptr) + image.offsets[1], | 873 static_cast<uint8*>(image_ptr) + image.offsets[1], |
891 image.pitches[1], | 874 image.pitches[1], |
892 image.width, | 875 image.width, |
893 image.height); | 876 image.height); |
894 } | 877 } |
895 | 878 |
896 va_res = vaUnmapBuffer(va_display_, image.buf); | 879 va_res = vaUnmapBuffer(va_display_, image.buf); |
897 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 880 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
898 | 881 |
899 return ret == 0; | 882 return ret == 0; |
900 } | 883 } |
901 | 884 |
902 bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id, | 885 bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id, |
903 VASurfaceID sync_surface_id, | 886 VASurfaceID sync_surface_id, |
904 uint8* target_ptr, | 887 uint8* target_ptr, |
905 size_t target_size, | 888 size_t target_size, |
906 size_t* coded_data_size) { | 889 size_t* coded_data_size) { |
907 base::AutoLock auto_lock(va_lock_); | 890 base::AutoLock auto_lock(*va_lock_); |
908 | 891 |
909 VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id); | 892 VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id); |
910 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 893 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
911 | 894 |
912 VACodedBufferSegment* buffer_segment = NULL; | 895 VACodedBufferSegment* buffer_segment = NULL; |
913 va_res = vaMapBuffer( | 896 va_res = vaMapBuffer( |
914 va_display_, buffer_id, reinterpret_cast<void**>(&buffer_segment)); | 897 va_display_, buffer_id, reinterpret_cast<void**>(&buffer_segment)); |
915 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); | 898 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); |
916 DCHECK(target_ptr); | 899 DCHECK(target_ptr); |
917 | 900 |
918 { | 901 { |
919 base::AutoUnlock auto_unlock(va_lock_); | 902 base::AutoUnlock auto_unlock(*va_lock_); |
920 *coded_data_size = 0; | 903 *coded_data_size = 0; |
921 | 904 |
922 while (buffer_segment) { | 905 while (buffer_segment) { |
923 DCHECK(buffer_segment->buf); | 906 DCHECK(buffer_segment->buf); |
924 | 907 |
925 if (buffer_segment->size > target_size) { | 908 if (buffer_segment->size > target_size) { |
926 LOG(ERROR) << "Insufficient output buffer size"; | 909 LOG(ERROR) << "Insufficient output buffer size"; |
927 break; | 910 break; |
928 } | 911 } |
929 | 912 |
(...skipping 16 matching lines...) Expand all Loading... |
946 | 929 |
947 DCHECK(coded_buffers_.erase(buffer_id)); | 930 DCHECK(coded_buffers_.erase(buffer_id)); |
948 | 931 |
949 return buffer_segment == NULL; | 932 return buffer_segment == NULL; |
950 } | 933 } |
951 | 934 |
952 bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src, | 935 bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src, |
953 const gfx::Size& src_size, | 936 const gfx::Size& src_size, |
954 VASurfaceID va_surface_id_dest, | 937 VASurfaceID va_surface_id_dest, |
955 const gfx::Size& dest_size) { | 938 const gfx::Size& dest_size) { |
956 base::AutoLock auto_lock(va_lock_); | 939 base::AutoLock auto_lock(*va_lock_); |
957 | 940 |
958 // Initialize the post processing engine if not already done. | 941 // Initialize the post processing engine if not already done. |
959 if (va_vpp_buffer_id_ == VA_INVALID_ID) { | 942 if (va_vpp_buffer_id_ == VA_INVALID_ID) { |
960 if (!InitializeVpp_Locked()) | 943 if (!InitializeVpp_Locked()) |
961 return false; | 944 return false; |
962 } | 945 } |
963 | 946 |
964 VAProcPipelineParameterBuffer* pipeline_param; | 947 VAProcPipelineParameterBuffer* pipeline_param; |
965 VA_SUCCESS_OR_RETURN(vaMapBuffer(va_display_, va_vpp_buffer_id_, | 948 VA_SUCCESS_OR_RETURN(vaMapBuffer(va_display_, va_vpp_buffer_id_, |
966 reinterpret_cast<void**>(&pipeline_param)), | 949 reinterpret_cast<void**>(&pipeline_param)), |
(...skipping 28 matching lines...) Expand all Loading... |
995 vaRenderPicture(va_display_, va_vpp_context_id_, &va_vpp_buffer_id_, 1), | 978 vaRenderPicture(va_display_, va_vpp_context_id_, &va_vpp_buffer_id_, 1), |
996 "Couldn't render picture", false); | 979 "Couldn't render picture", false); |
997 | 980 |
998 VA_SUCCESS_OR_RETURN(vaEndPicture(va_display_, va_vpp_context_id_), | 981 VA_SUCCESS_OR_RETURN(vaEndPicture(va_display_, va_vpp_context_id_), |
999 "Couldn't end picture", false); | 982 "Couldn't end picture", false); |
1000 | 983 |
1001 return true; | 984 return true; |
1002 } | 985 } |
1003 | 986 |
1004 bool VaapiWrapper::InitializeVpp_Locked() { | 987 bool VaapiWrapper::InitializeVpp_Locked() { |
1005 va_lock_.AssertAcquired(); | 988 va_lock_->AssertAcquired(); |
1006 | 989 |
1007 VA_SUCCESS_OR_RETURN( | 990 VA_SUCCESS_OR_RETURN( |
1008 vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc, NULL, 0, | 991 vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc, NULL, 0, |
1009 &va_vpp_config_id_), | 992 &va_vpp_config_id_), |
1010 "Couldn't create config", false); | 993 "Couldn't create config", false); |
1011 | 994 |
1012 // The size of the picture for the context is irrelevant in the case | 995 // The size of the picture for the context is irrelevant in the case |
1013 // of the VPP, just passing 1x1. | 996 // of the VPP, just passing 1x1. |
1014 VA_SUCCESS_OR_RETURN(vaCreateContext(va_display_, va_vpp_config_id_, 1, 1, 0, | 997 VA_SUCCESS_OR_RETURN(vaCreateContext(va_display_, va_vpp_config_id_, 1, 1, 0, |
1015 NULL, 0, &va_vpp_context_id_), | 998 NULL, 0, &va_vpp_context_id_), |
1016 "Couldn't create context", false); | 999 "Couldn't create context", false); |
1017 | 1000 |
1018 VA_SUCCESS_OR_RETURN(vaCreateBuffer(va_display_, va_vpp_context_id_, | 1001 VA_SUCCESS_OR_RETURN(vaCreateBuffer(va_display_, va_vpp_context_id_, |
1019 VAProcPipelineParameterBufferType, | 1002 VAProcPipelineParameterBufferType, |
1020 sizeof(VAProcPipelineParameterBuffer), 1, | 1003 sizeof(VAProcPipelineParameterBuffer), 1, |
1021 NULL, &va_vpp_buffer_id_), | 1004 NULL, &va_vpp_buffer_id_), |
1022 "Couldn't create buffer", false); | 1005 "Couldn't create buffer", false); |
1023 | 1006 |
1024 return true; | 1007 return true; |
1025 } | 1008 } |
1026 | 1009 |
1027 void VaapiWrapper::DeinitializeVpp() { | 1010 void VaapiWrapper::DeinitializeVpp() { |
1028 base::AutoLock auto_lock(va_lock_); | 1011 base::AutoLock auto_lock(*va_lock_); |
1029 | 1012 |
1030 if (va_vpp_buffer_id_ != VA_INVALID_ID) { | 1013 if (va_vpp_buffer_id_ != VA_INVALID_ID) { |
1031 vaDestroyBuffer(va_display_, va_vpp_buffer_id_); | 1014 vaDestroyBuffer(va_display_, va_vpp_buffer_id_); |
1032 va_vpp_buffer_id_ = VA_INVALID_ID; | 1015 va_vpp_buffer_id_ = VA_INVALID_ID; |
1033 } | 1016 } |
1034 if (va_vpp_context_id_ != VA_INVALID_ID) { | 1017 if (va_vpp_context_id_ != VA_INVALID_ID) { |
1035 vaDestroyContext(va_display_, va_vpp_context_id_); | 1018 vaDestroyContext(va_display_, va_vpp_context_id_); |
1036 va_vpp_context_id_ = VA_INVALID_ID; | 1019 va_vpp_context_id_ = VA_INVALID_ID; |
1037 } | 1020 } |
1038 if (va_vpp_config_id_ != VA_INVALID_ID) { | 1021 if (va_vpp_config_id_ != VA_INVALID_ID) { |
1039 vaDestroyConfig(va_display_, va_vpp_config_id_); | 1022 vaDestroyConfig(va_display_, va_vpp_config_id_); |
1040 va_vpp_config_id_ = VA_INVALID_ID; | 1023 va_vpp_config_id_ = VA_INVALID_ID; |
1041 } | 1024 } |
1042 } | 1025 } |
1043 | 1026 |
1044 // static | 1027 // static |
| 1028 void VaapiWrapper::PreSandboxInitialization() { |
| 1029 #if defined(USE_OZONE) |
| 1030 const char* kDriRenderNode0Path = "/dev/dri/renderD128"; |
| 1031 base::File drm_file = base::File( |
| 1032 base::FilePath::FromUTF8Unsafe(kDriRenderNode0Path), |
| 1033 base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE); |
| 1034 if (drm_file.IsValid()) |
| 1035 va_display_state_.Get().SetDrmFd(drm_file.GetPlatformFile()); |
| 1036 #endif |
| 1037 } |
| 1038 |
| 1039 // static |
1045 bool VaapiWrapper::PostSandboxInitialization() { | 1040 bool VaapiWrapper::PostSandboxInitialization() { |
1046 StubPathMap paths; | 1041 StubPathMap paths; |
1047 | 1042 |
1048 paths[kModuleVa].push_back("libva.so.1"); | 1043 paths[kModuleVa].push_back("libva.so.1"); |
1049 | 1044 |
1050 #if defined(USE_X11) | 1045 #if defined(USE_X11) |
1051 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | 1046 paths[kModuleVa_x11].push_back("libva-x11.so.1"); |
1052 #elif defined(USE_OZONE) | 1047 #elif defined(USE_OZONE) |
1053 paths[kModuleVa_drm].push_back("libva-drm.so.1"); | 1048 paths[kModuleVa_drm].push_back("libva-drm.so.1"); |
1054 #endif | 1049 #endif |
(...skipping 25 matching lines...) Expand all Loading... |
1080 | 1075 |
1081 bool VaapiWrapper::LazyProfileInfos::IsProfileSupported( | 1076 bool VaapiWrapper::LazyProfileInfos::IsProfileSupported( |
1082 CodecMode mode, VAProfile va_profile) { | 1077 CodecMode mode, VAProfile va_profile) { |
1083 for (const auto& profile : supported_profiles_[mode]) { | 1078 for (const auto& profile : supported_profiles_[mode]) { |
1084 if (profile.va_profile == va_profile) | 1079 if (profile.va_profile == va_profile) |
1085 return true; | 1080 return true; |
1086 } | 1081 } |
1087 return false; | 1082 return false; |
1088 } | 1083 } |
1089 | 1084 |
| 1085 VaapiWrapper::VADisplayState::VADisplayState() |
| 1086 : refcount_(0), |
| 1087 va_display_(nullptr), |
| 1088 major_version_(-1), |
| 1089 minor_version_(-1), |
| 1090 va_initialized_(false) {} |
| 1091 |
| 1092 VaapiWrapper::VADisplayState::~VADisplayState() {} |
| 1093 |
| 1094 bool VaapiWrapper::VADisplayState::Initialize(VAStatus* status) { |
| 1095 va_lock_.AssertAcquired(); |
| 1096 if (refcount_++ == 0) { |
| 1097 #if defined(USE_X11) |
| 1098 va_display_ = vaGetDisplay(gfx::GetXDisplay()); |
| 1099 #elif defined(USE_OZONE) |
| 1100 va_display_ = vaGetDisplayDRM(drm_fd_.get()); |
| 1101 #endif // USE_X11 |
| 1102 |
| 1103 if (!vaDisplayIsValid(va_display_)) { |
| 1104 LOG(ERROR) << "Could not get a valid VA display"; |
| 1105 return false; |
| 1106 } |
| 1107 |
| 1108 *status = vaInitialize(va_display_, &major_version_, &minor_version_); |
| 1109 if (*status != VA_STATUS_SUCCESS) |
| 1110 return false; |
| 1111 |
| 1112 va_initialized_ = true; |
| 1113 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; |
| 1114 } |
| 1115 |
| 1116 if (VAAPIVersionLessThan(0, 34)) { |
| 1117 LOG(ERROR) << "VAAPI version < 0.34 is not supported."; |
| 1118 return false; |
| 1119 } |
| 1120 return true; |
| 1121 } |
| 1122 |
| 1123 void VaapiWrapper::VADisplayState::Deinitialize(VAStatus* status) { |
| 1124 va_lock_.AssertAcquired(); |
| 1125 if (--refcount_ > 0) |
| 1126 return; |
| 1127 |
| 1128 // Must check if vaInitialize completed successfully, to work around a bug in |
| 1129 // libva. The bug was fixed upstream: |
| 1130 // http://lists.freedesktop.org/archives/libva/2013-July/001807.html |
| 1131 // TODO(mgiuca): Remove this check, and the |va_initialized_| variable, once |
| 1132 // the fix has rolled out sufficiently. |
| 1133 if (va_initialized_ && va_display_) { |
| 1134 *status = vaTerminate(va_display_); |
| 1135 } |
| 1136 va_initialized_ = false; |
| 1137 va_display_ = nullptr; |
| 1138 } |
| 1139 |
| 1140 #if defined(USE_OZONE) |
| 1141 void VaapiWrapper::VADisplayState::SetDrmFd(base::PlatformFile fd) { |
| 1142 drm_fd_.reset(HANDLE_EINTR(dup(fd))); |
| 1143 } |
| 1144 #endif // USE_OZONE |
| 1145 |
| 1146 bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) { |
| 1147 return (major_version_ < major) || |
| 1148 (major_version_ == major && minor_version_ < minor); |
| 1149 } |
| 1150 |
1090 } // namespace content | 1151 } // namespace content |
OLD | NEW |