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