| 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 |