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 |