视频编解码(五)之vdpau存在的意义?

一、概述

VA-API和VDPAU是video硬件加速的两种接口。

1. VAAPI-to-VDPAU

AI中的回答:

user: vaapi to vdpau

answer:

VA-API (Video Acceleration API) and VDPAU (Video Decode and Presentation API for Unix) are two different APIs that provide hardware acceleration support for video decoding, encoding, and processing on Linux systems.

To translate between VA-API and VDPAU, you would need to use a software layer or library that can convert the API calls made by one API to the other.

One such library is libva-vdpau-driver, which provides a VDPAU backend for VA-API. This library allows applications that use VA-API to utilize VDPAU for hardware acceleration, without requiring any changes to the application code. To use this library, you will need to have both VA-API and VDPAU installed on your system, as well as a compatible graphics driver.

On the other hand, if you want to translate VDPAU calls to VA-API, you can use the vdpau-va-driver library. This library provides a VA-API backend for VDPAU, allowing VDPAU applications to utilize VA-API for hardware acceleration. Again, you will need to have both VDPAU and VA-API installed on your system, along with a compatible graphics driver.

VDPAU was originally designed by Nvidia for their PureVideo SIP block present on their GeForce 8 series and later GPUs.

2. VDPAU in Wayland

VDPAU一般是在X11系统中使用的,Wayland中要使用VDPAU就有点复杂,不过理论上也不是不可以,按照下面方法(AI回答)

Using VDPAU with Wayland can be a bit more complex than using it with X11, as Wayland has a different architecture and protocol for interacting with graphics hardware.

To use VDPAU in Wayland, you will need to have the appropriate backend installed in your system. The default backend used by Wayland is EGLStreams, which is not compatible with VDPAU. However, there is an alternative backend called GBM (Generic Buffer Manager) that is compatible with VDPAU.

To use VDPAU with GBM in Wayland, you will need to install the following components:

  1. A compatible graphics driver that supports VDPAU and GBM. Nvidia provides a proprietary graphics driver that supports both of these technologies.

  2. The libva-vdpau-driver library, which provides a VDPAU backend for VA-API. This library allows Wayland applications that use VA-API to utilize VDPAU for hardware acceleration.

  3. A Wayland compositor that supports GBM. Most modern Wayland compositors, such as Weston and Sway, support GBM by default.

Once you have these components installed, you can configure your Wayland session to use the GBM backend by setting the EGL_PLATFORM environment variable to gbm. You can then test VDPAU acceleration by running a VDPAU-enabled application under Wayland and monitoring its GPU usage using a tool like nvidia-smi.

Note that VDPAU support in Wayland is still relatively new and may not be as stable or well-supported as it is in X11.

3. Nvidia support VDPAU

VDPAU最初是Nvidia设计的,Nvidia显卡支持VDPAU的可以在Nvidia PureVideo网页查询。

PureVideo HD是Nvidia开发的一种支持硬件加速处理视频播放的技术:

PureVideo HD is a technology developed by Nvidia that enhances the quality of video playback on computers and other devices. It uses hardware acceleration to offload video processing tasks from the CPU, resulting in smoother and higher-quality video playback. PureVideo HD supports a range of video formats, including H.264, MPEG-2, VC-1, and others, and can also improve the quality of standard-definition videos when upscaled to high-definition resolutions.

其中GTX 1050Ti显卡支持VDPAU情况:

graphic card GPU chip PureVideo VDPAU support
GeForce GTX 1050, GTX 1050 Ti GP107 VP8 H

这里的VP8并不是视频标准VP8,而是指Nvidia第8代PureVideo HD功能:

The eighth generation of PureVideo HD, introduced with the GeForce GTX 1080, GTX 1070, GTX 1060, GTX 1050 Ti & GTX 1050, GT 1030 & GT 1010, a Pascal (microarchitecture) GPU, adds full hardware-decode of HEVC Version 2 Main 12 profile, and increases the resolution for VP9 and HEVC decoding to 8K, including 8K UHDTV and up to 8K fulldome 8192x8192.

The eighth generation PureVideo HD is sometimes called “PureVideo HD 8” or “VP8”.

这里的VDPAU支持程度H表示支持加速VP9 profile并且能够支持HEVC和VP9的8k:

Supports complete acceleration of VP9 profile 2 (10-bit) and maximum resolution of up to 8192 x 8192 pixels (8k resolution) for all HEVC and VP9 profiles

二、libva-vdpau-drvier

这里libva-vdpau-driver和vdpau-driver其实是同一个驱动,名字叫法不同。

freedesktop给出了vaapi转vdpau的驱动代码vdpau-driver,不过其最新更新日期是2012年,适用libva的版本还停留在libva-0.32。

1. 初始化__vaDriverInit_x_x

libva, __vaDriverInit_x_x
vdpau-driver, __vaDriverInit_x_x
vdpau-driver, VA_DRIVER_INIT_FUNC
__vaDriverInit_0_31
vdpau_Initialize_Current

vdpau-driver中在configure中定义了**__vaDriverInit_x_x**函数接口

VA_DRIVER_INIT_FUNC="__vaDriverInit_${VA_MAJOR_VERSION}_${VA_MINOR_VERSION}"

然则,其在VA_DRIER_INIT_FUNC()函数中会直接判断当前libva版本,如果是0.31,则直接调用__vaDriverInit_0_31()函数:

VAStatus VA_DRIVER_INIT_FUNC(void *ctx)
{
   
#if VA_MAJOR_VERSION == 0 && VA_MINOR_VERSION == 31
    return __vaDriverInit_0_31(ctx);
#endif
    return vdpau_Initialize_Current(ctx);
}

否则进入vdpau_Initialize_Current()函数来初始化,其中会调用vdpau_common_Initialize()函数:

vdpau_Initialize_Current()函数:

static VAStatus FUNC(Initialize)(VA_DRIVER_CONTEXT_P ctx)
{
   
    struct vdpau_driver_data *driver_data;

    driver_data = calloc(1, sizeof(*driver_data));
    if (!driver_data)
        return VA_STATUS_ERROR_ALLOCATION_FAILED;

    ctx->pDriverData            = driver_data;
    driver_data->x11_dpy        = ctx->native_dpy;
    driver_data->x11_screen     = ctx->x11_screen;

    VAStatus va_status = vdpau_common_Initialize(driver_data);
    if (va_status != VA_STATUS_SUCCESS) {
   
        FUNC(Terminate)(ctx);
        return va_status;
    }

    ctx->version_major          = VA_INIT_VERSION_MAJOR;
    ctx->version_minor          = VA_INIT_VERSION_MINOR;
    ctx->max_profiles           = VDPAU_MAX_PROFILES;
    ctx->max_entrypoints        = VDPAU_MAX_ENTRYPOINTS;
    ctx->max_attributes         = VDPAU_MAX_CONFIG_ATTRIBUTES;
    ctx->max_image_formats      = VDPAU_MAX_IMAGE_FORMATS;
    ctx->max_subpic_formats     = VDPAU_MAX_SUBPICTURE_FORMATS;
    ctx->max_display_attributes = VDPAU_MAX_DISPLAY_ATTRIBUTES;
    ctx->str_vendor             = driver_data->va_vendor;

    struct VA_DRIVER_VTABLE *vtable;
#if VA_INIT_CHECK_VERSION(0,32,0)
    vtable = ctx->vtable;
#else
    vtable = &ctx->vtable;
#endif
    memset(vtable, 0, sizeof(*vtable));
    vtable->vaTerminate                     = FUNC(Terminate);
    vtable->vaQueryConfigEntrypoints        = vdpau_QueryConfigEntrypoints;
    vtable->vaQueryConfigProfiles           = vdpau_QueryConfigProfiles;
    vtable->vaQueryConfigEntrypoints        = vdpau_QueryConfigEntrypoints;
    vtable->vaQueryConfigAttributes         = vdpau_QueryConfigAttributes;
    vtable->vaCreateConfig                  = vdpau_CreateConfig;
    vtable->vaDestroyConfig                 = vdpau_DestroyConfig;
    vtable->vaGetConfigAttributes           = vdpau_GetConfigAttributes;
    vtable->vaCreateSurfaces                = vdpau_CreateSurfaces;
    vtable->vaDestroySurfaces               = vdpau_DestroySurfaces;
    vtable->vaCreateContext                 = vdpau_CreateContext;
    vtable->vaDestroyContext                = vdpau_DestroyContext;
    vtable->vaCreateBuffer                  = vdpau_CreateBuffer;
    vtable->vaBufferSetNumElements          = vdpau_BufferSetNumElements;
    vtable->vaMapBuffer                     = vdpau_MapBuffer;
    vtable->vaUnmapBuffer                   = vdpau_UnmapBuffer;
    vtable->vaDestroyBuffer                 = vdpau_DestroyBuffer;
    vtable->vaBeginPicture                  = vdpau_BeginPicture;
    vtable->vaRenderPicture                 = vdpau_RenderPicture;
    vtable->vaEndPicture                    = vdpau_EndPicture;
#if VA_INIT_CHECK_VERSION(0,31,0)
    vtable->vaSyncSurface                   = vdpau_SyncSurface2;
#else
    vtable->vaSyncSurface                   = vdpau_SyncSurface3;
#endif
    vtable->vaQuerySurfaceStatus            = vdpau_QuerySurfaceStatus;
    vtable->vaPutSurface                    = vdpau_PutSurface;
    vtable->vaQueryImageFormats             = vdpau_QueryImageFormats;
    vtable->vaCreateImage                   = vdpau_CreateImage;
    vtable->vaDeriveImage                   = vdpau_DeriveImage;
    vtable->vaDestroyImage                  = vdpau_DestroyImage;
    vtable->vaSetImagePalette               = vdpau_SetImagePalette;
    vtable->vaGetImage                      = vdpau_GetImage;
#if VA_INIT_CHECK_VERSION(0,31,0)
    vtable->vaPutImage                      = vdpau_PutImage_full;
#else
    vtable->vaPutImage                      = vdpau_PutImage;
    vtable->vaPutImage2                     = vdpau_PutImage_full;
#endif
    vtable->vaQuerySubpictureFormats        = vdpau_QuerySubpictureFormats;
    vtable->vaCreateSubpicture              = vdpau_CreateSubpicture;
    vtable->vaDestroySubpicture             = vdpau_DestroySubpicture;
    vtable->vaSetSubpictureImage            = vdpau_SetSubpictureImage;
    vtable->vaSetSubpictureChromakey        = vdpau_SetSubpictureChromakey;
    vtable->vaSetSubpictureGlobalAlpha      = vdpau_SetSubpictureGlobalAlpha;
#if VA_INIT_CHECK_VERSION(0,31,0)
    vtable->vaAssociateSubpicture           = vdpau_AssociateSubpicture_full;
#else
    vtable->vaAssociateSubpicture           = vdpau_AssociateSubpicture;
    vtable->vaAssociateSubpicture2          = vdpau_AssociateSubpicture_full;
#endif
    vtable->vaDeassociateSubpicture         = vdpau_DeassociateSubpicture;
    vtable->vaQueryDisplayAttributes        = vdpau_QueryDisplayAttributes;
    vtable->vaGetDisplayAttributes          = vdpau_GetDisplayAttributes;
    vtable->vaSetDisplayAttributes          = vdpau_SetDisplayAttributes;
#if VA_INIT_CHECK_VERSION(0,31,1)
#if VA_INIT_CHECK_VERSION(0,32,0)
    vtable->vaBufferInfo                    = vdpau_BufferInfo;
#else
    vtable->vaBufferInfo                    = vdpau_BufferInfo_0_31_1;
#endif
    vtable->vaLockSurface                   = vdpau_LockSurface;
    vtable->vaUnlockSurface                 = vdpau_UnlockSurface;
#else
#if VA_INIT_CHECK_VERSION(0,30,0)
    vtable->vaCreateSurfaceFromCIFrame      = vdpau_CreateSurfaceFromCIFrame;
    vtable->vaCreateSurfaceFromV4L2Buf      = vdpau_CreateSurfaceFromV4L2Buf;
    vtable->vaCopySurfaceToBuffer           = vdpau_CopySurfaceToBuffer;
#else
    vtable->vaSetSubpicturePalette          = vdpau_SetSubpicturePalette;
    vtable->vaDbgCopySurfaceToBuffer        = vdpau_DbgCopySurfaceToBuffer;
#endif
#endif

#if VA_INIT_GLX
    VA_DRIVER_VTABLE_GLX_P const glx_vtable = FUNC(GetVTableGLX)(ctx);
    if (!glx_vtable)
        return VA_STATUS_ERROR_ALLOCATION_FAILED;
    glx_vtable->vaCreateSurfaceGLX          = vdpau_CreateSurfaceGLX;
    glx_vtable->vaDestroySurfaceGLX         = vdpau_DestroySurfaceGLX;
    glx_vtable->vaCopySurfaceGLX            = vdpau_CopySurfaceGLX;
#endif
    return VA_STATUS_SUCCESS;
}

vdpau_comon_Initialize()函数,其使用x11,GLX。

static VAStatus vdpau_common_Initialize(vdpau_driver_data_t *driver_data)
{
   
    /* Create a dedicated X11 display for VDPAU purposes */
    const char * const x11_dpy_name = XDisplayString(driver_data->x11_dpy);
    driver_data->vdp_dpy = XOpenDisplay(x11_dpy_name);
    if (!driver_data->vdp_dpy)
        return VA_STATUS_ERROR_UNKNOWN;

    VdpStatus vdp_status;
    driver_data->vdp_device = VDP_INVALID_HANDLE;
    vdp_status = vdp_device_create_x11(
        driver_data->vdp_dpy,
        driver_data->x11_screen,
        &driver_data->vdp_device,
        &driver_data->vdp_get_proc_address
    );
    if (vdp_status != VDP_STATUS_OK)
        return VA_STATUS_ERROR_UNKNOWN;

    if (vdpau_gate_init(driver_data) < 0)
        return VA_STATUS_ERROR_UNKNOWN;

    uint32_t api_version;
    vdp_status = vdpau_get_api_version(driver_data, &api_version);
    if (vdp_status != VDP_STATUS_OK)
        return vdpau_get_VAStatus(vdp_status);
    if (api_version != VDPAU_VERSION)
        return VA_STATUS_ERROR_UNKNOWN;

    const char *impl_string = NULL;
    vdp_status = vdpau_get_information_string(driver_data, &impl_string);
    if (vdp_status != VDP_STATUS_OK)
        return vdpau_get_VAStatus(vdp_status);
    if (impl_string) {
   
        const char *str, *version_string = NULL;
        D(bug("%s\n", impl_string));

        if (strncmp(impl_string, "NVIDIA", 6) == 0) {
   
            /* NVIDIA VDPAU Driver Shared Library  <version>  <date> */
            driver_data->vdp_impl_type = VDP_IMPLEMENTATION_NVIDIA;
            for (str = impl_string; *str; str++) {
   
                if (isdigit(*str)) {
   
                    version_string = str;
                    break;
                }
            }
        }

        if (version_string) {
   
            int major, minor;
            if (sscanf(version_string, "%d.%d", &major, &minor) == 2)
                driver_data->vdp_impl_version = (major << 16) | minor;
        }
    }

    sprintf(driver_data->va_vendor, "%s %s - %d.%d.%d",
            VDPAU_STR_DRIVER_VENDOR,
            VDPAU_STR_DRIVER_NAME,
            VDPAU_VIDEO_MAJOR_VERSION,
            VDPAU_VIDEO_MINOR_VERSION,
            VDPAU_VIDEO_MICRO_VERSION);

    if (VDPAU_VIDEO_PRE_VERSION > 0) {
   
        const int len = strlen(driver_data->va_vendor);
        sprintf(&driver_data->va_vendor[len], ".pre%d", VDPAU_VIDEO_PRE_VERSION);
    }

    CREATE_HEAP(config,         CONFIG);
    CREATE_HEAP(context,        CONTEXT);
    CREATE_HEAP(surface,        SURFACE);
    CREATE_HEAP(buffer,         BUFFER);
    CREATE_HEAP(output,         OUTPUT);
    CREATE_HEAP(image,          IMAGE);
    CREATE_HEAP(subpicture,     SUBPICTURE);
    CREATE_HEAP(mixer,          MIXER);
#if USE_GLX
    CREATE_HEAP(glx_surface,    GLX_SURFACE);
#endif
    return VA_STATUS_SUCCESS;
}

vdpau_common_Initialize()函数会读取Nvidia card的驱动driver信息等,如使用vdpauinfo命令便可以查看

Information string: NVIDIA VDPAU Driver Shared Library 530.41.03

vdpau_Initialize_Current()函数中初始化了vtable,vtable是留给VA-API接口调用下来使用的,然后这里做了转换,从VA-API转成VDPAU的接口。

2. VAAPI中的vtable

libva
vdpau-driver, vtable
vdpau-driver, VDPAU VTable
libvdpau
driver

以**vaEndPicture()**为例分析下流程

对于VA-API中,用户程序比如mpv player,通过libavcodec调用vaEndPicture(),然后进入libva的vaEndPicture(),由libva进入驱动层的vtable对应的函数处理。在vdpau-driver中vtable中并不能直接开始处理,还需要再转到下一层vdpau再去处理,所以这里的vtable只是一层中间转换层。

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值