| Index: content/common/gpu/media/vaapi_wrapper.cc
|
| diff --git a/content/common/gpu/media/vaapi_wrapper.cc b/content/common/gpu/media/vaapi_wrapper.cc
|
| deleted file mode 100644
|
| index ab4e176e4ec0e869448e192728bcce4a80257d46..0000000000000000000000000000000000000000
|
| --- a/content/common/gpu/media/vaapi_wrapper.cc
|
| +++ /dev/null
|
| @@ -1,1274 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "content/common/gpu/media/vaapi_wrapper.h"
|
| -
|
| -#include <dlfcn.h>
|
| -#include <string.h>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/callback_helpers.h"
|
| -#include "base/logging.h"
|
| -#include "base/macros.h"
|
| -#include "base/numerics/safe_conversions.h"
|
| -#include "base/sys_info.h"
|
| -#include "build/build_config.h"
|
| -// Auto-generated for dlopen libva libraries
|
| -#include "content/common/gpu/media/va_stubs.h"
|
| -#include "content/common/gpu/media/vaapi_picture.h"
|
| -#include "third_party/libyuv/include/libyuv.h"
|
| -#include "ui/gl/gl_bindings.h"
|
| -#if defined(USE_X11)
|
| -#include "ui/gfx/x/x11_types.h"
|
| -#elif defined(USE_OZONE)
|
| -#include "third_party/libva/va/drm/va_drm.h"
|
| -#include "third_party/libva/va/va_drmcommon.h"
|
| -#include "ui/ozone/public/ozone_platform.h"
|
| -#include "ui/ozone/public/surface_factory_ozone.h"
|
| -#endif // USE_X11
|
| -
|
| -using content_common_gpu_media::kModuleVa;
|
| -#if defined(USE_X11)
|
| -using content_common_gpu_media::kModuleVa_x11;
|
| -#elif defined(USE_OZONE)
|
| -using content_common_gpu_media::kModuleVa_drm;
|
| -#endif // USE_X11
|
| -using content_common_gpu_media::InitializeStubs;
|
| -using content_common_gpu_media::StubPathMap;
|
| -
|
| -#define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \
|
| - do { \
|
| - LOG(ERROR) << err_msg \
|
| - << " VA error: " << vaErrorStr(va_error); \
|
| - report_error_to_uma_cb_.Run(); \
|
| - } while (0)
|
| -
|
| -#define VA_LOG_ON_ERROR(va_error, err_msg) \
|
| - do { \
|
| - if ((va_error) != VA_STATUS_SUCCESS) \
|
| - LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \
|
| - } while (0)
|
| -
|
| -#define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \
|
| - do { \
|
| - if ((va_error) != VA_STATUS_SUCCESS) { \
|
| - LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \
|
| - return (ret); \
|
| - } \
|
| - } while (0)
|
| -
|
| -#if defined(USE_OZONE)
|
| -namespace {
|
| -
|
| -uint32_t BufferFormatToVAFourCC(gfx::BufferFormat fmt) {
|
| - switch (fmt) {
|
| - case gfx::BufferFormat::BGRX_8888:
|
| - return VA_FOURCC_BGRX;
|
| - case gfx::BufferFormat::UYVY_422:
|
| - return VA_FOURCC_UYVY;
|
| - default:
|
| - NOTREACHED();
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| -uint32_t BufferFormatToVARTFormat(gfx::BufferFormat fmt) {
|
| - switch (fmt) {
|
| - case gfx::BufferFormat::UYVY_422:
|
| - return VA_RT_FORMAT_YUV422;
|
| - case gfx::BufferFormat::BGRX_8888:
|
| - return VA_RT_FORMAT_RGB32;
|
| - default:
|
| - NOTREACHED();
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -#endif
|
| -
|
| -namespace content {
|
| -
|
| -// Maximum framerate of encoded profile. This value is an arbitary limit
|
| -// and not taken from HW documentation.
|
| -const int kMaxEncoderFramerate = 30;
|
| -
|
| -base::LazyInstance<VaapiWrapper::VADisplayState>
|
| - VaapiWrapper::va_display_state_ = LAZY_INSTANCE_INITIALIZER;
|
| -
|
| -base::LazyInstance<VaapiWrapper::LazyProfileInfos>
|
| - VaapiWrapper::profile_infos_ = LAZY_INSTANCE_INITIALIZER;
|
| -
|
| -// Config attributes common for both encode and decode.
|
| -static const VAConfigAttrib kCommonVAConfigAttribs[] = {
|
| - {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420},
|
| -};
|
| -
|
| -// Attributes required for encode.
|
| -static const VAConfigAttrib kEncodeVAConfigAttribs[] = {
|
| - {VAConfigAttribRateControl, VA_RC_CBR},
|
| - {VAConfigAttribEncPackedHeaders,
|
| - VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE},
|
| -};
|
| -
|
| -struct ProfileMap {
|
| - media::VideoCodecProfile profile;
|
| - VAProfile va_profile;
|
| -};
|
| -
|
| -// A map between VideoCodecProfile and VAProfile.
|
| -static const ProfileMap kProfileMap[] = {
|
| - {media::H264PROFILE_BASELINE, VAProfileH264Baseline},
|
| - {media::H264PROFILE_MAIN, VAProfileH264Main},
|
| - // TODO(posciak): See if we can/want support other variants of
|
| - // media::H264PROFILE_HIGH*.
|
| - {media::H264PROFILE_HIGH, VAProfileH264High},
|
| - {media::VP8PROFILE_ANY, VAProfileVP8Version0_3},
|
| - // TODO(servolk): Need to add VP9 profiles 1,2,3 here after rolling
|
| - // third_party/libva to 1.7. crbug.com/598118
|
| - {media::VP9PROFILE_PROFILE0, VAProfileVP9Profile0},
|
| -};
|
| -
|
| -static std::vector<VAConfigAttrib> GetRequiredAttribs(
|
| - VaapiWrapper::CodecMode mode) {
|
| - std::vector<VAConfigAttrib> required_attribs;
|
| - required_attribs.insert(
|
| - required_attribs.end(),
|
| - kCommonVAConfigAttribs,
|
| - kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs));
|
| - if (mode == VaapiWrapper::kEncode) {
|
| - required_attribs.insert(
|
| - required_attribs.end(),
|
| - kEncodeVAConfigAttribs,
|
| - kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs));
|
| - }
|
| - return required_attribs;
|
| -}
|
| -
|
| -VASurface::VASurface(VASurfaceID va_surface_id,
|
| - const gfx::Size& size,
|
| - unsigned int format,
|
| - const ReleaseCB& release_cb)
|
| - : va_surface_id_(va_surface_id),
|
| - size_(size),
|
| - format_(format),
|
| - release_cb_(release_cb) {
|
| - DCHECK(!release_cb_.is_null());
|
| -}
|
| -
|
| -VASurface::~VASurface() {
|
| - release_cb_.Run(va_surface_id_);
|
| -}
|
| -
|
| -VaapiWrapper::VaapiWrapper()
|
| - : va_surface_format_(0),
|
| - va_display_(NULL),
|
| - va_config_id_(VA_INVALID_ID),
|
| - va_context_id_(VA_INVALID_ID),
|
| - va_vpp_config_id_(VA_INVALID_ID),
|
| - va_vpp_context_id_(VA_INVALID_ID),
|
| - va_vpp_buffer_id_(VA_INVALID_ID) {
|
| - va_lock_ = va_display_state_.Get().va_lock();
|
| -}
|
| -
|
| -VaapiWrapper::~VaapiWrapper() {
|
| - DestroyPendingBuffers();
|
| - DestroyCodedBuffers();
|
| - DestroySurfaces();
|
| - DeinitializeVpp();
|
| - Deinitialize();
|
| -}
|
| -
|
| -// static
|
| -scoped_refptr<VaapiWrapper> VaapiWrapper::Create(
|
| - CodecMode mode,
|
| - VAProfile va_profile,
|
| - const base::Closure& report_error_to_uma_cb) {
|
| - if (!profile_infos_.Get().IsProfileSupported(mode, va_profile)) {
|
| - DVLOG(1) << "Unsupported va_profile: " << va_profile;
|
| - return nullptr;
|
| - }
|
| -
|
| - scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper());
|
| - if (vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) {
|
| - if (vaapi_wrapper->Initialize(mode, va_profile))
|
| - return vaapi_wrapper;
|
| - }
|
| - LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: " << va_profile;
|
| - return nullptr;
|
| -}
|
| -
|
| -// static
|
| -scoped_refptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec(
|
| - CodecMode mode,
|
| - media::VideoCodecProfile profile,
|
| - const base::Closure& report_error_to_uma_cb) {
|
| - VAProfile va_profile = ProfileToVAProfile(profile, mode);
|
| - scoped_refptr<VaapiWrapper> vaapi_wrapper =
|
| - Create(mode, va_profile, report_error_to_uma_cb);
|
| - return vaapi_wrapper;
|
| -}
|
| -
|
| -// static
|
| -media::VideoEncodeAccelerator::SupportedProfiles
|
| -VaapiWrapper::GetSupportedEncodeProfiles() {
|
| - media::VideoEncodeAccelerator::SupportedProfiles profiles;
|
| - std::vector<ProfileInfo> encode_profile_infos =
|
| - profile_infos_.Get().GetSupportedProfileInfosForCodecMode(kEncode);
|
| -
|
| - for (size_t i = 0; i < arraysize(kProfileMap); ++i) {
|
| - VAProfile va_profile = ProfileToVAProfile(kProfileMap[i].profile, kEncode);
|
| - if (va_profile == VAProfileNone)
|
| - continue;
|
| - for (const auto& profile_info : encode_profile_infos) {
|
| - if (profile_info.va_profile == va_profile) {
|
| - media::VideoEncodeAccelerator::SupportedProfile profile;
|
| - profile.profile = kProfileMap[i].profile;
|
| - profile.max_resolution = profile_info.max_resolution;
|
| - profile.max_framerate_numerator = kMaxEncoderFramerate;
|
| - profile.max_framerate_denominator = 1;
|
| - profiles.push_back(profile);
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - return profiles;
|
| -}
|
| -
|
| -// static
|
| -media::VideoDecodeAccelerator::SupportedProfiles
|
| -VaapiWrapper::GetSupportedDecodeProfiles() {
|
| - media::VideoDecodeAccelerator::SupportedProfiles profiles;
|
| - std::vector<ProfileInfo> decode_profile_infos =
|
| - profile_infos_.Get().GetSupportedProfileInfosForCodecMode(kDecode);
|
| -
|
| - for (size_t i = 0; i < arraysize(kProfileMap); ++i) {
|
| - VAProfile va_profile = ProfileToVAProfile(kProfileMap[i].profile, kDecode);
|
| - if (va_profile == VAProfileNone)
|
| - continue;
|
| - for (const auto& profile_info : decode_profile_infos) {
|
| - if (profile_info.va_profile == va_profile) {
|
| - media::VideoDecodeAccelerator::SupportedProfile profile;
|
| - profile.profile = kProfileMap[i].profile;
|
| - profile.max_resolution = profile_info.max_resolution;
|
| - profile.min_resolution.SetSize(16, 16);
|
| - profiles.push_back(profile);
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - return profiles;
|
| -}
|
| -
|
| -// static
|
| -bool VaapiWrapper::IsJpegDecodeSupported() {
|
| - return profile_infos_.Get().IsProfileSupported(kDecode,
|
| - VAProfileJPEGBaseline);
|
| -}
|
| -
|
| -void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| - VADisplayAttribute item = {VADisplayAttribRenderMode,
|
| - 1, // At least support '_LOCAL_OVERLAY'.
|
| - -1, // The maximum possible support 'ALL'.
|
| - VA_RENDER_MODE_LOCAL_GPU,
|
| - VA_DISPLAY_ATTRIB_SETTABLE};
|
| -
|
| - VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1);
|
| - if (va_res != VA_STATUS_SUCCESS)
|
| - DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default.";
|
| -}
|
| -
|
| -// static
|
| -VAProfile VaapiWrapper::ProfileToVAProfile(
|
| - media::VideoCodecProfile profile, CodecMode mode) {
|
| - VAProfile va_profile = VAProfileNone;
|
| - for (size_t i = 0; i < arraysize(kProfileMap); ++i) {
|
| - if (kProfileMap[i].profile == profile) {
|
| - va_profile = kProfileMap[i].va_profile;
|
| - break;
|
| - }
|
| - }
|
| - if (!profile_infos_.Get().IsProfileSupported(mode, va_profile) &&
|
| - va_profile == VAProfileH264Baseline) {
|
| - // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips
|
| - // the information whether the profile is constrained or not, so we have no
|
| - // way to know here. Try for baseline first, but if it is not supported,
|
| - // try constrained baseline and hope this is what it actually is
|
| - // (which in practice is true for a great majority of cases).
|
| - if (profile_infos_.Get().IsProfileSupported(
|
| - mode, VAProfileH264ConstrainedBaseline)) {
|
| - va_profile = VAProfileH264ConstrainedBaseline;
|
| - DVLOG(1) << "Fall back to constrained baseline profile.";
|
| - }
|
| - }
|
| - return va_profile;
|
| -}
|
| -
|
| -std::vector<VaapiWrapper::ProfileInfo>
|
| -VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) {
|
| - std::vector<ProfileInfo> supported_profile_infos;
|
| - std::vector<VAProfile> va_profiles;
|
| - if (!GetSupportedVaProfiles(&va_profiles))
|
| - return supported_profile_infos;
|
| -
|
| - std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode);
|
| - VAEntrypoint entrypoint =
|
| - (mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD);
|
| -
|
| - base::AutoLock auto_lock(*va_lock_);
|
| - for (const auto& va_profile : va_profiles) {
|
| - if (!IsEntrypointSupported_Locked(va_profile, entrypoint))
|
| - continue;
|
| - if (!AreAttribsSupported_Locked(va_profile, entrypoint, required_attribs))
|
| - continue;
|
| - ProfileInfo profile_info;
|
| - if (!GetMaxResolution_Locked(va_profile,
|
| - entrypoint,
|
| - required_attribs,
|
| - &profile_info.max_resolution)) {
|
| - LOG(ERROR) << "GetMaxResolution failed for va_profile " << va_profile
|
| - << " and entrypoint " << entrypoint;
|
| - continue;
|
| - }
|
| - profile_info.va_profile = va_profile;
|
| - supported_profile_infos.push_back(profile_info);
|
| - }
|
| - return supported_profile_infos;
|
| -}
|
| -
|
| -bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) {
|
| - static bool vaapi_functions_initialized = PostSandboxInitialization();
|
| - if (!vaapi_functions_initialized) {
|
| - bool running_on_chromeos = false;
|
| -#if defined(OS_CHROMEOS)
|
| - // When chrome runs on linux with chromeos=1, do not log error message
|
| - // without VAAPI libraries.
|
| - running_on_chromeos = base::SysInfo::IsRunningOnChromeOS();
|
| -#endif
|
| - static const char kErrorMsg[] = "Failed to initialize VAAPI libs";
|
| - if (running_on_chromeos)
|
| - LOG(ERROR) << kErrorMsg;
|
| - else
|
| - DVLOG(1) << kErrorMsg;
|
| - return false;
|
| - }
|
| -
|
| - report_error_to_uma_cb_ = report_error_to_uma_cb;
|
| -
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - VADisplayState* va_display_state = &va_display_state_.Get();
|
| - if (!va_display_state) {
|
| - LOG(ERROR) << "Failed to allocate VA display state";
|
| - return false;
|
| - }
|
| -
|
| - if (!va_display_state->Initialize())
|
| - return false;
|
| -
|
| - va_display_ = va_display_state->va_display();
|
| - return true;
|
| -}
|
| -
|
| -bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| - // Query the driver for supported profiles.
|
| - int max_profiles = vaMaxNumProfiles(va_display_);
|
| - std::vector<VAProfile> supported_profiles(
|
| - base::checked_cast<size_t>(max_profiles));
|
| -
|
| - int num_supported_profiles;
|
| - VAStatus va_res = vaQueryConfigProfiles(
|
| - va_display_, &supported_profiles[0], &num_supported_profiles);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false);
|
| - if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) {
|
| - LOG(ERROR) << "vaQueryConfigProfiles returned: " << num_supported_profiles;
|
| - return false;
|
| - }
|
| -
|
| - supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles));
|
| - *profiles = supported_profiles;
|
| - return true;
|
| -}
|
| -
|
| -bool VaapiWrapper::IsEntrypointSupported_Locked(VAProfile va_profile,
|
| - VAEntrypoint entrypoint) {
|
| - va_lock_->AssertAcquired();
|
| - // Query the driver for supported entrypoints.
|
| - int max_entrypoints = vaMaxNumEntrypoints(va_display_);
|
| - std::vector<VAEntrypoint> supported_entrypoints(
|
| - base::checked_cast<size_t>(max_entrypoints));
|
| -
|
| - int num_supported_entrypoints;
|
| - VAStatus va_res = vaQueryConfigEntrypoints(va_display_,
|
| - va_profile,
|
| - &supported_entrypoints[0],
|
| - &num_supported_entrypoints);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false);
|
| - if (num_supported_entrypoints < 0 ||
|
| - num_supported_entrypoints > max_entrypoints) {
|
| - LOG(ERROR) << "vaQueryConfigEntrypoints returned: "
|
| - << num_supported_entrypoints;
|
| - return false;
|
| - }
|
| -
|
| - if (std::find(supported_entrypoints.begin(),
|
| - supported_entrypoints.end(),
|
| - entrypoint) == supported_entrypoints.end()) {
|
| - DVLOG(1) << "Unsupported entrypoint";
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool VaapiWrapper::AreAttribsSupported_Locked(
|
| - VAProfile va_profile,
|
| - VAEntrypoint entrypoint,
|
| - const std::vector<VAConfigAttrib>& required_attribs) {
|
| - va_lock_->AssertAcquired();
|
| - // Query the driver for required attributes.
|
| - std::vector<VAConfigAttrib> attribs = required_attribs;
|
| - for (size_t i = 0; i < required_attribs.size(); ++i)
|
| - attribs[i].value = 0;
|
| -
|
| - VAStatus va_res = vaGetConfigAttributes(
|
| - va_display_, va_profile, entrypoint, &attribs[0], attribs.size());
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false);
|
| -
|
| - for (size_t i = 0; i < required_attribs.size(); ++i) {
|
| - if (attribs[i].type != required_attribs[i].type ||
|
| - (attribs[i].value & required_attribs[i].value) !=
|
| - required_attribs[i].value) {
|
| - DVLOG(1) << "Unsupported value " << required_attribs[i].value
|
| - << " for attribute type " << required_attribs[i].type;
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool VaapiWrapper::GetMaxResolution_Locked(
|
| - VAProfile va_profile,
|
| - VAEntrypoint entrypoint,
|
| - std::vector<VAConfigAttrib>& required_attribs,
|
| - gfx::Size* resolution) {
|
| - va_lock_->AssertAcquired();
|
| - VAConfigID va_config_id;
|
| - VAStatus va_res = vaCreateConfig(
|
| - va_display_,
|
| - va_profile,
|
| - entrypoint,
|
| - &required_attribs[0],
|
| - required_attribs.size(),
|
| - &va_config_id);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false);
|
| -
|
| - // Calls vaQuerySurfaceAttributes twice. The first time is to get the number
|
| - // of attributes to prepare the space and the second time is to get all
|
| - // attributes.
|
| - unsigned int num_attribs;
|
| - va_res = vaQuerySurfaceAttributes(
|
| - va_display_, va_config_id, nullptr, &num_attribs);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false);
|
| - if (!num_attribs)
|
| - return false;
|
| -
|
| - std::vector<VASurfaceAttrib> attrib_list(
|
| - base::checked_cast<size_t>(num_attribs));
|
| -
|
| - va_res = vaQuerySurfaceAttributes(
|
| - va_display_, va_config_id, &attrib_list[0], &num_attribs);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaQuerySurfaceAttributes failed", false);
|
| -
|
| - resolution->SetSize(0, 0);
|
| - for (const auto& attrib : attrib_list) {
|
| - if (attrib.type == VASurfaceAttribMaxWidth)
|
| - resolution->set_width(attrib.value.value.i);
|
| - else if (attrib.type == VASurfaceAttribMaxHeight)
|
| - resolution->set_height(attrib.value.value.i);
|
| - }
|
| - if (resolution->IsEmpty()) {
|
| - LOG(ERROR) << "Codec resolution " << resolution->ToString()
|
| - << " cannot be zero.";
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) {
|
| - TryToSetVADisplayAttributeToLocalGPU();
|
| -
|
| - VAEntrypoint entrypoint =
|
| - (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
|
| - std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode);
|
| - base::AutoLock auto_lock(*va_lock_);
|
| - VAStatus va_res = vaCreateConfig(va_display_,
|
| - va_profile,
|
| - entrypoint,
|
| - &required_attribs[0],
|
| - required_attribs.size(),
|
| - &va_config_id_);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void VaapiWrapper::Deinitialize() {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - if (va_config_id_ != VA_INVALID_ID) {
|
| - VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_);
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed");
|
| - }
|
| -
|
| - VADisplayState* va_display_state = &va_display_state_.Get();
|
| - if (va_display_state) {
|
| - VAStatus va_res = VA_STATUS_SUCCESS;
|
| - va_display_state->Deinitialize(&va_res);
|
| - VA_LOG_ON_ERROR(va_res, "vaTerminate failed");
|
| - }
|
| -
|
| - va_config_id_ = VA_INVALID_ID;
|
| - va_display_ = NULL;
|
| -}
|
| -
|
| -bool VaapiWrapper::CreateSurfaces(unsigned int va_format,
|
| - const gfx::Size& size,
|
| - size_t num_surfaces,
|
| - std::vector<VASurfaceID>* va_surfaces) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| - DVLOG(2) << "Creating " << num_surfaces << " surfaces";
|
| -
|
| - DCHECK(va_surfaces->empty());
|
| - DCHECK(va_surface_ids_.empty());
|
| - DCHECK_EQ(va_surface_format_, 0u);
|
| - va_surface_ids_.resize(num_surfaces);
|
| -
|
| - // Allocate surfaces in driver.
|
| - VAStatus va_res =
|
| - vaCreateSurfaces(va_display_, va_format, size.width(), size.height(),
|
| - &va_surface_ids_[0], va_surface_ids_.size(), NULL, 0);
|
| -
|
| - VA_LOG_ON_ERROR(va_res, "vaCreateSurfaces failed");
|
| - if (va_res != VA_STATUS_SUCCESS) {
|
| - va_surface_ids_.clear();
|
| - return false;
|
| - }
|
| -
|
| - // And create a context associated with them.
|
| - va_res = vaCreateContext(va_display_, va_config_id_,
|
| - size.width(), size.height(), VA_PROGRESSIVE,
|
| - &va_surface_ids_[0], va_surface_ids_.size(),
|
| - &va_context_id_);
|
| -
|
| - VA_LOG_ON_ERROR(va_res, "vaCreateContext failed");
|
| - if (va_res != VA_STATUS_SUCCESS) {
|
| - DestroySurfaces();
|
| - return false;
|
| - }
|
| -
|
| - *va_surfaces = va_surface_ids_;
|
| - va_surface_format_ = va_format;
|
| - return true;
|
| -}
|
| -
|
| -void VaapiWrapper::DestroySurfaces() {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| - DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces";
|
| -
|
| - if (va_context_id_ != VA_INVALID_ID) {
|
| - VAStatus va_res = vaDestroyContext(va_display_, va_context_id_);
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed");
|
| - }
|
| -
|
| - if (!va_surface_ids_.empty()) {
|
| - VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_ids_[0],
|
| - va_surface_ids_.size());
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed");
|
| - }
|
| -
|
| - va_surface_ids_.clear();
|
| - va_context_id_ = VA_INVALID_ID;
|
| - va_surface_format_ = 0;
|
| -}
|
| -
|
| -scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface(
|
| - unsigned int va_format,
|
| - const gfx::Size& size,
|
| - const std::vector<VASurfaceAttrib>& va_attribs) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - std::vector<VASurfaceAttrib> attribs(va_attribs);
|
| - VASurfaceID va_surface_id;
|
| - VAStatus va_res =
|
| - vaCreateSurfaces(va_display_, va_format, size.width(), size.height(),
|
| - &va_surface_id, 1, &attribs[0], attribs.size());
|
| -
|
| - scoped_refptr<VASurface> va_surface;
|
| - VA_SUCCESS_OR_RETURN(va_res, "Failed to create unowned VASurface",
|
| - va_surface);
|
| -
|
| - // This is safe to use Unretained() here, because the VDA takes care
|
| - // of the destruction order. All the surfaces will be destroyed
|
| - // before VaapiWrapper.
|
| - va_surface = new VASurface(
|
| - va_surface_id, size, va_format,
|
| - base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this)));
|
| -
|
| - return va_surface;
|
| -}
|
| -
|
| -#if defined(USE_OZONE)
|
| -scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForPixmap(
|
| - const scoped_refptr<ui::NativePixmap>& pixmap) {
|
| - // Get the dmabuf of the created buffer.
|
| - int dmabuf_fd = pixmap->GetDmaBufFd();
|
| - if (dmabuf_fd < 0) {
|
| - LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap";
|
| - return nullptr;
|
| - }
|
| - int dmabuf_pitch = pixmap->GetDmaBufPitch();
|
| - gfx::Size pixmap_size = pixmap->GetBufferSize();
|
| -
|
| - // Create a VASurface out of the created buffer using the dmabuf.
|
| - VASurfaceAttribExternalBuffers va_attrib_extbuf;
|
| - memset(&va_attrib_extbuf, 0, sizeof(va_attrib_extbuf));
|
| - va_attrib_extbuf.pixel_format =
|
| - BufferFormatToVAFourCC(pixmap->GetBufferFormat());
|
| - va_attrib_extbuf.width = pixmap_size.width();
|
| - va_attrib_extbuf.height = pixmap_size.height();
|
| - va_attrib_extbuf.data_size = pixmap_size.height() * dmabuf_pitch;
|
| - va_attrib_extbuf.num_planes = 1;
|
| - va_attrib_extbuf.pitches[0] = dmabuf_pitch;
|
| - va_attrib_extbuf.offsets[0] = 0;
|
| - va_attrib_extbuf.buffers = reinterpret_cast<unsigned long*>(&dmabuf_fd);
|
| - va_attrib_extbuf.num_buffers = 1;
|
| - va_attrib_extbuf.flags = 0;
|
| - va_attrib_extbuf.private_data = NULL;
|
| -
|
| - std::vector<VASurfaceAttrib> va_attribs;
|
| - va_attribs.resize(2);
|
| -
|
| - va_attribs[0].type = VASurfaceAttribMemoryType;
|
| - va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
|
| - va_attribs[0].value.type = VAGenericValueTypeInteger;
|
| - va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
|
| -
|
| - va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor;
|
| - va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
|
| - va_attribs[1].value.type = VAGenericValueTypePointer;
|
| - va_attribs[1].value.value.p = &va_attrib_extbuf;
|
| -
|
| - scoped_refptr<VASurface> va_surface =
|
| - CreateUnownedSurface(BufferFormatToVARTFormat(pixmap->GetBufferFormat()),
|
| - pixmap_size, va_attribs);
|
| - if (!va_surface) {
|
| - LOG(ERROR) << "Failed to create VASurface for an Ozone NativePixmap";
|
| - return nullptr;
|
| - }
|
| -
|
| - return va_surface;
|
| -}
|
| -
|
| -bool VaapiWrapper::ProcessPixmap(
|
| - const scoped_refptr<ui::NativePixmap>& source_pixmap,
|
| - scoped_refptr<ui::NativePixmap> target_pixmap) {
|
| - scoped_refptr<VASurface> va_surface = CreateVASurfaceForPixmap(source_pixmap);
|
| - if (!va_surface) {
|
| - LOG(ERROR) << "Failed creating VA Surface for source_pixmap";
|
| - return false;
|
| - }
|
| -
|
| - scoped_refptr<VASurface> processed_va_surface =
|
| - CreateVASurfaceForPixmap(target_pixmap);
|
| - if (!processed_va_surface) {
|
| - LOG(ERROR) << "Failed creating processed VA Surface for pixmap";
|
| - return false;
|
| - }
|
| -
|
| - if (!BlitSurface(va_surface, processed_va_surface)) {
|
| - LOG(ERROR) << "Failed scaling NativePixmap";
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -#endif
|
| -
|
| -void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1);
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed");
|
| -}
|
| -
|
| -bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
|
| - size_t size,
|
| - void* buffer) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - VABufferID buffer_id;
|
| - VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_,
|
| - va_buffer_type, size,
|
| - 1, buffer, &buffer_id);
|
| - VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false);
|
| -
|
| - switch (va_buffer_type) {
|
| - case VASliceParameterBufferType:
|
| - case VASliceDataBufferType:
|
| - case VAEncSliceParameterBufferType:
|
| - pending_slice_bufs_.push_back(buffer_id);
|
| - break;
|
| -
|
| - default:
|
| - pending_va_bufs_.push_back(buffer_id);
|
| - break;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool VaapiWrapper::SubmitVAEncMiscParamBuffer(
|
| - VAEncMiscParameterType misc_param_type,
|
| - size_t size,
|
| - void* buffer) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - VABufferID buffer_id;
|
| - VAStatus va_res = vaCreateBuffer(va_display_,
|
| - va_context_id_,
|
| - VAEncMiscParameterBufferType,
|
| - sizeof(VAEncMiscParameterBuffer) + size,
|
| - 1,
|
| - NULL,
|
| - &buffer_id);
|
| - VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false);
|
| -
|
| - void* data_ptr = NULL;
|
| - va_res = vaMapBuffer(va_display_, buffer_id, &data_ptr);
|
| - VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed");
|
| - if (va_res != VA_STATUS_SUCCESS) {
|
| - vaDestroyBuffer(va_display_, buffer_id);
|
| - return false;
|
| - }
|
| -
|
| - DCHECK(data_ptr);
|
| -
|
| - VAEncMiscParameterBuffer* misc_param =
|
| - reinterpret_cast<VAEncMiscParameterBuffer*>(data_ptr);
|
| - misc_param->type = misc_param_type;
|
| - memcpy(misc_param->data, buffer, size);
|
| - va_res = vaUnmapBuffer(va_display_, buffer_id);
|
| - VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
|
| -
|
| - pending_va_bufs_.push_back(buffer_id);
|
| - return true;
|
| -}
|
| -
|
| -void VaapiWrapper::DestroyPendingBuffers() {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - for (const auto& pending_va_buf : pending_va_bufs_) {
|
| - VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_buf);
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
|
| - }
|
| -
|
| - for (const auto& pending_slice_buf : pending_slice_bufs_) {
|
| - VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_buf);
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
|
| - }
|
| -
|
| - pending_va_bufs_.clear();
|
| - pending_slice_bufs_.clear();
|
| -}
|
| -
|
| -bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| - VAStatus va_res = vaCreateBuffer(va_display_,
|
| - va_context_id_,
|
| - VAEncCodedBufferType,
|
| - size,
|
| - 1,
|
| - NULL,
|
| - buffer_id);
|
| - VA_SUCCESS_OR_RETURN(va_res, "Failed to create a coded buffer", false);
|
| -
|
| - const auto is_new_entry = coded_buffers_.insert(*buffer_id).second;
|
| - DCHECK(is_new_entry);
|
| - return true;
|
| -}
|
| -
|
| -void VaapiWrapper::DestroyCodedBuffers() {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin();
|
| - iter != coded_buffers_.end();
|
| - ++iter) {
|
| - VAStatus va_res = vaDestroyBuffer(va_display_, *iter);
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
|
| - }
|
| -
|
| - coded_buffers_.clear();
|
| -}
|
| -
|
| -bool VaapiWrapper::Execute(VASurfaceID va_surface_id) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size();
|
| - DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size();
|
| - DVLOG(4) << "Target VA surface " << va_surface_id;
|
| -
|
| - // Get ready to execute for given surface.
|
| - VAStatus va_res = vaBeginPicture(va_display_, va_context_id_,
|
| - va_surface_id);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false);
|
| -
|
| - if (pending_va_bufs_.size() > 0) {
|
| - // Commit parameter and slice buffers.
|
| - va_res = vaRenderPicture(va_display_,
|
| - va_context_id_,
|
| - &pending_va_bufs_[0],
|
| - pending_va_bufs_.size());
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false);
|
| - }
|
| -
|
| - if (pending_slice_bufs_.size() > 0) {
|
| - va_res = vaRenderPicture(va_display_,
|
| - va_context_id_,
|
| - &pending_slice_bufs_[0],
|
| - pending_slice_bufs_.size());
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false);
|
| - }
|
| -
|
| - // Instruct HW codec to start processing committed buffers.
|
| - // Does not block and the job is not finished after this returns.
|
| - va_res = vaEndPicture(va_display_, va_context_id_);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) {
|
| - bool result = Execute(va_surface_id);
|
| - DestroyPendingBuffers();
|
| - return result;
|
| -}
|
| -
|
| -#if defined(USE_X11)
|
| -bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
|
| - Pixmap x_pixmap,
|
| - gfx::Size dest_size) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
|
| - VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
|
| -
|
| - // Put the data into an X Pixmap.
|
| - va_res = vaPutSurface(va_display_,
|
| - va_surface_id,
|
| - x_pixmap,
|
| - 0, 0, dest_size.width(), dest_size.height(),
|
| - 0, 0, dest_size.width(), dest_size.height(),
|
| - NULL, 0, 0);
|
| - VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false);
|
| - return true;
|
| -}
|
| -#endif // USE_X11
|
| -
|
| -bool VaapiWrapper::GetDerivedVaImage(VASurfaceID va_surface_id,
|
| - VAImage* image,
|
| - void** mem) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
|
| - VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
|
| -
|
| - // Derive a VAImage from the VASurface
|
| - va_res = vaDeriveImage(va_display_, va_surface_id, image);
|
| - VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed");
|
| - if (va_res != VA_STATUS_SUCCESS)
|
| - return false;
|
| -
|
| - // Map the VAImage into memory
|
| - va_res = vaMapBuffer(va_display_, image->buf, mem);
|
| - VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed");
|
| - if (va_res == VA_STATUS_SUCCESS)
|
| - return true;
|
| -
|
| - va_res = vaDestroyImage(va_display_, image->image_id);
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed");
|
| -
|
| - return false;
|
| -}
|
| -
|
| -bool VaapiWrapper::GetVaImage(VASurfaceID va_surface_id,
|
| - VAImageFormat* format,
|
| - const gfx::Size& size,
|
| - VAImage* image,
|
| - void** mem) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
|
| - VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
|
| -
|
| - va_res =
|
| - vaCreateImage(va_display_, format, size.width(), size.height(), image);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaCreateImage failed", false);
|
| -
|
| - va_res = vaGetImage(va_display_, va_surface_id, 0, 0, size.width(),
|
| - size.height(), image->image_id);
|
| - VA_LOG_ON_ERROR(va_res, "vaGetImage failed");
|
| -
|
| - if (va_res == VA_STATUS_SUCCESS) {
|
| - // Map the VAImage into memory
|
| - va_res = vaMapBuffer(va_display_, image->buf, mem);
|
| - VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed");
|
| - }
|
| -
|
| - if (va_res != VA_STATUS_SUCCESS) {
|
| - va_res = vaDestroyImage(va_display_, image->image_id);
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed");
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void VaapiWrapper::ReturnVaImage(VAImage* image) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - VAStatus va_res = vaUnmapBuffer(va_display_, image->buf);
|
| - VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
|
| -
|
| - va_res = vaDestroyImage(va_display_, image->image_id);
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed");
|
| -}
|
| -
|
| -static void DestroyVAImage(VADisplay va_display, VAImage image) {
|
| - if (image.image_id != VA_INVALID_ID)
|
| - vaDestroyImage(va_display, image.image_id);
|
| -}
|
| -
|
| -bool VaapiWrapper::UploadVideoFrameToSurface(
|
| - const scoped_refptr<media::VideoFrame>& frame,
|
| - VASurfaceID va_surface_id) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - VAImage image;
|
| - VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false);
|
| - base::ScopedClosureRunner vaimage_deleter(
|
| - base::Bind(&DestroyVAImage, va_display_, image));
|
| -
|
| - if (image.format.fourcc != VA_FOURCC_NV12) {
|
| - LOG(ERROR) << "Unsupported image format: " << image.format.fourcc;
|
| - return false;
|
| - }
|
| -
|
| - if (gfx::Rect(image.width, image.height) < gfx::Rect(frame->coded_size())) {
|
| - LOG(ERROR) << "Buffer too small to fit the frame.";
|
| - return false;
|
| - }
|
| -
|
| - void* image_ptr = NULL;
|
| - va_res = vaMapBuffer(va_display_, image.buf, &image_ptr);
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false);
|
| - DCHECK(image_ptr);
|
| -
|
| - int ret = 0;
|
| - {
|
| - base::AutoUnlock auto_unlock(*va_lock_);
|
| - ret = libyuv::I420ToNV12(
|
| - frame->data(media::VideoFrame::kYPlane),
|
| - frame->stride(media::VideoFrame::kYPlane),
|
| - frame->data(media::VideoFrame::kUPlane),
|
| - frame->stride(media::VideoFrame::kUPlane),
|
| - frame->data(media::VideoFrame::kVPlane),
|
| - frame->stride(media::VideoFrame::kVPlane),
|
| - static_cast<uint8_t*>(image_ptr) + image.offsets[0], image.pitches[0],
|
| - static_cast<uint8_t*>(image_ptr) + image.offsets[1], image.pitches[1],
|
| - image.width, image.height);
|
| - }
|
| -
|
| - va_res = vaUnmapBuffer(va_display_, image.buf);
|
| - VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
|
| -
|
| - return ret == 0;
|
| -}
|
| -
|
| -bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
|
| - VASurfaceID sync_surface_id,
|
| - uint8_t* target_ptr,
|
| - size_t target_size,
|
| - size_t* coded_data_size) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id);
|
| - VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
|
| -
|
| - VACodedBufferSegment* buffer_segment = NULL;
|
| - va_res = vaMapBuffer(
|
| - va_display_, buffer_id, reinterpret_cast<void**>(&buffer_segment));
|
| - VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false);
|
| - DCHECK(target_ptr);
|
| -
|
| - {
|
| - base::AutoUnlock auto_unlock(*va_lock_);
|
| - *coded_data_size = 0;
|
| -
|
| - while (buffer_segment) {
|
| - DCHECK(buffer_segment->buf);
|
| -
|
| - if (buffer_segment->size > target_size) {
|
| - LOG(ERROR) << "Insufficient output buffer size";
|
| - break;
|
| - }
|
| -
|
| - memcpy(target_ptr, buffer_segment->buf, buffer_segment->size);
|
| -
|
| - target_ptr += buffer_segment->size;
|
| - *coded_data_size += buffer_segment->size;
|
| - target_size -= buffer_segment->size;
|
| -
|
| - buffer_segment =
|
| - reinterpret_cast<VACodedBufferSegment*>(buffer_segment->next);
|
| - }
|
| - }
|
| -
|
| - va_res = vaUnmapBuffer(va_display_, buffer_id);
|
| - VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
|
| -
|
| - va_res = vaDestroyBuffer(va_display_, buffer_id);
|
| - VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
|
| -
|
| - const auto was_found = coded_buffers_.erase(buffer_id);
|
| - DCHECK(was_found);
|
| -
|
| - return buffer_segment == NULL;
|
| -}
|
| -
|
| -bool VaapiWrapper::BlitSurface(
|
| - const scoped_refptr<VASurface>& va_surface_src,
|
| - const scoped_refptr<VASurface>& va_surface_dest) {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - // Initialize the post processing engine if not already done.
|
| - if (va_vpp_buffer_id_ == VA_INVALID_ID) {
|
| - if (!InitializeVpp_Locked())
|
| - return false;
|
| - }
|
| -
|
| - VAProcPipelineParameterBuffer* pipeline_param;
|
| - VA_SUCCESS_OR_RETURN(vaMapBuffer(va_display_, va_vpp_buffer_id_,
|
| - reinterpret_cast<void**>(&pipeline_param)),
|
| - "Couldn't map vpp buffer", false);
|
| -
|
| - memset(pipeline_param, 0, sizeof *pipeline_param);
|
| - const gfx::Size src_size = va_surface_src->size();
|
| - const gfx::Size dest_size = va_surface_dest->size();
|
| -
|
| - VARectangle input_region;
|
| - input_region.x = input_region.y = 0;
|
| - input_region.width = src_size.width();
|
| - input_region.height = src_size.height();
|
| - pipeline_param->surface_region = &input_region;
|
| - pipeline_param->surface = va_surface_src->id();
|
| - pipeline_param->surface_color_standard = VAProcColorStandardNone;
|
| -
|
| - VARectangle output_region;
|
| - output_region.x = output_region.y = 0;
|
| - output_region.width = dest_size.width();
|
| - output_region.height = dest_size.height();
|
| - pipeline_param->output_region = &output_region;
|
| - pipeline_param->output_background_color = 0xff000000;
|
| - pipeline_param->output_color_standard = VAProcColorStandardNone;
|
| - pipeline_param->filter_flags = VA_FILTER_SCALING_HQ;
|
| -
|
| - VA_SUCCESS_OR_RETURN(vaUnmapBuffer(va_display_, va_vpp_buffer_id_),
|
| - "Couldn't unmap vpp buffer", false);
|
| -
|
| - VA_SUCCESS_OR_RETURN(
|
| - vaBeginPicture(va_display_, va_vpp_context_id_, va_surface_dest->id()),
|
| - "Couldn't begin picture", false);
|
| -
|
| - VA_SUCCESS_OR_RETURN(
|
| - vaRenderPicture(va_display_, va_vpp_context_id_, &va_vpp_buffer_id_, 1),
|
| - "Couldn't render picture", false);
|
| -
|
| - VA_SUCCESS_OR_RETURN(vaEndPicture(va_display_, va_vpp_context_id_),
|
| - "Couldn't end picture", false);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool VaapiWrapper::InitializeVpp_Locked() {
|
| - va_lock_->AssertAcquired();
|
| -
|
| - VA_SUCCESS_OR_RETURN(
|
| - vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc, NULL, 0,
|
| - &va_vpp_config_id_),
|
| - "Couldn't create config", false);
|
| -
|
| - // The size of the picture for the context is irrelevant in the case
|
| - // of the VPP, just passing 1x1.
|
| - VA_SUCCESS_OR_RETURN(vaCreateContext(va_display_, va_vpp_config_id_, 1, 1, 0,
|
| - NULL, 0, &va_vpp_context_id_),
|
| - "Couldn't create context", false);
|
| -
|
| - VA_SUCCESS_OR_RETURN(vaCreateBuffer(va_display_, va_vpp_context_id_,
|
| - VAProcPipelineParameterBufferType,
|
| - sizeof(VAProcPipelineParameterBuffer), 1,
|
| - NULL, &va_vpp_buffer_id_),
|
| - "Couldn't create buffer", false);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void VaapiWrapper::DeinitializeVpp() {
|
| - base::AutoLock auto_lock(*va_lock_);
|
| -
|
| - if (va_vpp_buffer_id_ != VA_INVALID_ID) {
|
| - vaDestroyBuffer(va_display_, va_vpp_buffer_id_);
|
| - va_vpp_buffer_id_ = VA_INVALID_ID;
|
| - }
|
| - if (va_vpp_context_id_ != VA_INVALID_ID) {
|
| - vaDestroyContext(va_display_, va_vpp_context_id_);
|
| - va_vpp_context_id_ = VA_INVALID_ID;
|
| - }
|
| - if (va_vpp_config_id_ != VA_INVALID_ID) {
|
| - vaDestroyConfig(va_display_, va_vpp_config_id_);
|
| - va_vpp_config_id_ = VA_INVALID_ID;
|
| - }
|
| -}
|
| -
|
| -// static
|
| -void VaapiWrapper::PreSandboxInitialization() {
|
| -#if defined(USE_OZONE)
|
| - const char kDriRenderNode0Path[] = "/dev/dri/renderD128";
|
| - base::File drm_file = base::File(
|
| - base::FilePath::FromUTF8Unsafe(kDriRenderNode0Path),
|
| - base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
|
| - if (drm_file.IsValid())
|
| - va_display_state_.Get().SetDrmFd(drm_file.GetPlatformFile());
|
| -#endif
|
| -}
|
| -
|
| -// static
|
| -bool VaapiWrapper::PostSandboxInitialization() {
|
| - StubPathMap paths;
|
| -
|
| - paths[kModuleVa].push_back("libva.so.1");
|
| -
|
| -#if defined(USE_X11)
|
| - paths[kModuleVa_x11].push_back("libva-x11.so.1");
|
| -#elif defined(USE_OZONE)
|
| - paths[kModuleVa_drm].push_back("libva-drm.so.1");
|
| -#endif
|
| -
|
| - return InitializeStubs(paths);
|
| -}
|
| -
|
| -VaapiWrapper::LazyProfileInfos::LazyProfileInfos() {
|
| - static_assert(arraysize(supported_profiles_) == kCodecModeMax,
|
| - "The array size of supported profile is incorrect.");
|
| - scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper());
|
| - if (!vaapi_wrapper->VaInitialize(base::Bind(&base::DoNothing)))
|
| - return;
|
| - for (size_t i = 0; i < kCodecModeMax; ++i) {
|
| - supported_profiles_[i] =
|
| - vaapi_wrapper->GetSupportedProfileInfosForCodecModeInternal(
|
| - static_cast<CodecMode>(i));
|
| - }
|
| -}
|
| -
|
| -VaapiWrapper::LazyProfileInfos::~LazyProfileInfos() {
|
| -}
|
| -
|
| -std::vector<VaapiWrapper::ProfileInfo>
|
| -VaapiWrapper::LazyProfileInfos::GetSupportedProfileInfosForCodecMode(
|
| - CodecMode mode) {
|
| - return supported_profiles_[mode];
|
| -}
|
| -
|
| -bool VaapiWrapper::LazyProfileInfos::IsProfileSupported(
|
| - CodecMode mode, VAProfile va_profile) {
|
| - for (const auto& profile : supported_profiles_[mode]) {
|
| - if (profile.va_profile == va_profile)
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -VaapiWrapper::VADisplayState::VADisplayState()
|
| - : refcount_(0),
|
| - va_display_(nullptr),
|
| - major_version_(-1),
|
| - minor_version_(-1),
|
| - va_initialized_(false) {}
|
| -
|
| -VaapiWrapper::VADisplayState::~VADisplayState() {}
|
| -
|
| -bool VaapiWrapper::VADisplayState::Initialize() {
|
| - va_lock_.AssertAcquired();
|
| - if (refcount_++ == 0) {
|
| -#if defined(USE_X11)
|
| - va_display_ = vaGetDisplay(gfx::GetXDisplay());
|
| -#elif defined(USE_OZONE)
|
| - va_display_ = vaGetDisplayDRM(drm_fd_.get());
|
| -#endif // USE_X11
|
| -
|
| - if (!vaDisplayIsValid(va_display_)) {
|
| - LOG(ERROR) << "Could not get a valid VA display";
|
| - return false;
|
| - }
|
| -
|
| - VAStatus va_res =
|
| - vaInitialize(va_display_, &major_version_, &minor_version_);
|
| - if (va_res != VA_STATUS_SUCCESS) {
|
| - LOG(WARNING) << "vaInitialize failed: " << vaErrorStr(va_res);
|
| - return false;
|
| - }
|
| -
|
| - va_initialized_ = true;
|
| - DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_;
|
| - }
|
| -
|
| - if (VAAPIVersionLessThan(0, 34)) {
|
| - LOG(ERROR) << "VAAPI version < 0.34 is not supported.";
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void VaapiWrapper::VADisplayState::Deinitialize(VAStatus* status) {
|
| - va_lock_.AssertAcquired();
|
| - if (--refcount_ > 0)
|
| - return;
|
| -
|
| - // Must check if vaInitialize completed successfully, to work around a bug in
|
| - // libva. The bug was fixed upstream:
|
| - // http://lists.freedesktop.org/archives/libva/2013-July/001807.html
|
| - // TODO(mgiuca): Remove this check, and the |va_initialized_| variable, once
|
| - // the fix has rolled out sufficiently.
|
| - if (va_initialized_ && va_display_) {
|
| - *status = vaTerminate(va_display_);
|
| - }
|
| - va_initialized_ = false;
|
| - va_display_ = nullptr;
|
| -}
|
| -
|
| -#if defined(USE_OZONE)
|
| -void VaapiWrapper::VADisplayState::SetDrmFd(base::PlatformFile fd) {
|
| - drm_fd_.reset(HANDLE_EINTR(dup(fd)));
|
| -}
|
| -#endif // USE_OZONE
|
| -
|
| -bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) {
|
| - return (major_version_ < major) ||
|
| - (major_version_ == major && minor_version_ < minor);
|
| -}
|
| -
|
| -} // namespace content
|
|
|