一、vainfo工具概述

vainfo是一个用于显示系统上VA-API(Video Acceleration API)配置信息和支持功能的命令行工具。它能够查询并展示系统视频加速硬件和驱动程序支持的编解码profile、entrypoint以及详细的配置参数,是开发和调试视频加速应用程序的重要工具。

项目地址:https://github.com/intel/libva-utils/blob/master/vainfo/vainfo.c

在这里插入图片描述

1. vainfo工具输出格式详解

通过分析vainfo.c文件的源代码,可以详细了解vainfo工具的输出格式生成逻辑。vainfo支持两种输出模式:基本输出模式和详细输出模式(使用-a选项)。

1.1 基本输出示例

默认情况下(不使用-a选项),vainfo会显示以下信息:

  1. VA-API版本和驱动版本信息
  2. 支持的编解码profile和entrypoint组合

以下是基本输出的示例格式:

libva info: VA-API version X.X.X
libva info: Driver version X.X.X
libva info: Trying to open /path/to/driver.so
libva info: Found init function __vaDriverInit_XX
vainfo: VA-API version: X.X.X (libva X.X.X)
vainfo: Driver version: X.X.X
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointVLD

1.2 详细输出示例(使用-a选项)

当使用-a或–all选项时,vainfo会显示每个profile/entrypoint组合的详细配置属性信息,包括像素格式、编码参数、解码参数等。

详细输出示例(部分):

libva info: VA-API version X.X.X
libva info: Driver version X.X.X
...
vainfo: VAProfileH264Main : VAEntrypointEncSlice
      VAConfigAttribRTFormat                    : VA_RT_FORMAT_YUV420
      VAConfigAttribEncRateControl              : VA_RC_CBR | VA_RC_VBR
      VAConfigAttribEncIntraRefresh             : VA_ENC_INTRA_REFRESH_MAX 1
      VAConfigAttribEncMaxRefFrames             : 16
      VAConfigAttribEncMaxSlices                : 16
      ...

2. main函数流程和功能分析

main函数是vainfo工具的核心,负责整个程序的执行流程。通过分析vainfo.c文件的main函数代码,可以详细了解其功能实现。

2.1 核心代码解析

main函数的核心实现代码如下:

int main(int argc, char **argv)
{
    VADisplay display;
    VAStatus va_status;
    int major_version, minor_version;
    int i, j, k, num_profiles, num_entrypoints, num_attribs;
    VAProfile *profile_list = NULL;
    VAEntrypoint *entrypoint_list = NULL;
    VAConfigAttrib *attrib_list = NULL;
    VAGenericID config_id;
    int ret = 0;
    const char *display_name = NULL;
    int option_index = 0;

    // 命令行参数解析
    parse_args(argc, argv, &display_name);

    // VA显示设备初始化
    display = va_open_display(display_name);
    if (!display)
        exit(1);

    // 查询VA-API版本
    va_status = vaInitialize(display, &major_version, &minor_version);
    CHECK_VASTATUS("vaInitialize", va_status);

    // 打印版本信息
    printf("vainfo: VA-API version: %d.%d (libva %d.%d.%d)\n", 
           major_version, minor_version, LIBVA_MAJOR_VERSION, 
           LIBVA_MINOR_VERSION, LIBVA_MICRO_VERSION);
    printf("vainfo: Driver version: %s\n", vaQueryVendorString(display));

    // 查询并显示配置信息
    va_status = vaQueryConfigProfiles(display, &profile_list, &num_profiles);
    CHECK_VASTATUS("vaQueryConfigProfiles", va_status);

    // 遍历所有profile
    for (i = 0; i < num_profiles; i++) {
        // 查询每个profile支持的entrypoint
        va_status = vaQueryConfigEntrypoints(display, profile_list[i], 
                                           &entrypoint_list, &num_entrypoints);
        CHECK_VASTATUS("vaQueryConfigEntrypoints", va_status);

        // 遍历所有entrypoint
        for (j = 0; j < num_entrypoints; j++) {
            // 根据show_all_opt决定输出模式
            if (show_all_opt) {
                // 详细模式:创建配置并查询属性
                va_status = vaCreateConfig(display, profile_list[i], 
                                          entrypoint_list[j], 
                                          NULL, 0, &config_id);
                if (va_status != VA_STATUS_SUCCESS) 
                    continue;
                
                // 查询并显示详细配置属性
                va_status = vaQueryConfigAttributes(display, profile_list[i], 
                                                  entrypoint_list[j], 
                                                  NULL, &num_attribs);
                if (va_status == VA_STATUS_SUCCESS) {
                    attrib_list = malloc(num_attribs * sizeof(VAConfigAttrib));
                    // 查询并显示属性
                    va_status = vaQueryConfigAttributes(display, 
                                                      profile_list[i], 
                                                      entrypoint_list[j], 
                                                      attrib_list, &num_attribs);
                    show_config_attributes(attrib_list, num_attribs);
                    free(attrib_list);
                }
                vaDestroyConfig(display, config_id);
            } else {
                // 基本模式:仅显示profile和entrypoint组合
                printf("      %-32s: %s\n", 
                       vaProfileStr(profile_list[i]), 
                       vaEntrypointStr(entrypoint_list[j]));
            }
        }
        free(entrypoint_list);
    }

    // 资源清理
    free(profile_list);
    vaTerminate(display);
    va_close_display(display);
    return ret;
}

2.2 执行流程详解

main函数的执行流程可以分为以下几个关键步骤:

  1. 初始化与参数解析

    • 调用parse_args函数解析命令行参数
    • 设置show_all_opt全局变量,控制是否显示详细配置属性
    • 支持的命令行选项包括--help-a/--all
  2. VA-API显示设备初始化

    • 调用va_open_display函数初始化VA显示设备
    • 调用vaInitialize函数初始化VA-API并获取版本信息
    • 使用CHECK_VASTATUS宏检查VA函数调用的返回状态
  3. 版本信息显示

    • 打印VA-API版本号(运行时版本和编译时版本)
    • 打印驱动程序版本信息
    • 这些信息由vaQueryVendorString函数获取
  4. 配置查询

    • 调用vaQueryConfigProfiles函数获取所有支持的profile
    • 对每个profile,调用vaQueryConfigEntrypoints函数获取其支持的entrypoint
    • 这些信息通过动态内存分配存储在profile_listentrypoint_list
  5. 输出模式

    • 默认模式:仅显示支持的profile和entrypoint组合,使用格式化输出
    • 详细模式(-a选项):对于每个profile/entrypoint组合:
      • 调用vaCreateConfig创建配置
      • 调用vaQueryConfigAttributes查询配置属性
      • 调用show_config_attributes函数显示详细属性信息
      • 调用vaDestroyConfig销毁配置
  6. 资源清理

    • 释放动态分配的内存
    • 调用vaTerminate终止VA-API会话
    • 调用va_close_display关闭显示设备

3. -a选项输出的编解码参数功能

使用-a选项时,vainfo会通过show_config_attributes函数输出详细的编解码参数。这些参数涵盖了视频处理的各个方面。

3.1 基本视频格式参数

这些参数定义了视频处理支持的基本格式和能力:

  • 像素格式支持(VAConfigAttribRTFormat)

    • 显示支持的YUV和RGB系列格式,如YUV420、YUV422、YUV444、RGB等
    • 代码实现:
      if (attrib_list[VAConfigAttribRTFormat].value != VA_ATTRIB_NOT_SUPPORTED) {
          printf("      VAConfigAttribRTFormat                    : ");
          print_rt_format(attrib_list[VAConfigAttribRTFormat].value);
          printf("\n");
      }
      
  • 空间残差(VAConfigAttribSpatialResidual)

    • 支持的空间残差处理能力,影响视频编码质量
  • 空间裁剪(VAConfigAttribSpatialCropping)

    • 是否支持视频帧的空间裁剪功能
  • 帧内残差(VAConfigAttribIntraResidual)

    • 帧内编码的残差处理支持情况
  • 加密属性(VAConfigAttribEncryption)

    • 内容保护相关功能支持,如DRM等

3.2 编码专用参数

这些参数特定于视频编码功能:

  • 码率控制模式(VAConfigAttribEncRateControl)

    • 支持的码率控制方式,如CBR(恒定码率)、VBR(可变码率)等
    • 代码实现:
      if (attrib_list[VAConfigAttribEncRateControl].value != VA_ATTRIB_NOT_SUPPORTED) {
          printf("      VAConfigAttribEncRateControl              : ");
          print_enc_rate_control(attrib_list[VAConfigAttribEncRateControl].value);
          printf("\n");
      }
      
  • 交织模式(VAConfigAttribEncInterlaced)

    • 是否支持隔行扫描编码
    • 代码实现:
      if (attrib_list[VAConfigAttribEncInterlaced].value != VA_ATTRIB_NOT_SUPPORTED) {
          printf("      VAConfigAttribEncInterlaced               : ");
          print_boolean(attrib_list[VAConfigAttribEncInterlaced].value);
          printf("\n");
      }
      
  • 最大参考帧(VAConfigAttribEncMaxRefFrames)

    • 编码时可使用的最大参考帧数
    • 影响编码效率和图像质量
  • 最大瓦片/切片数(VAConfigAttribEncMaxTemporalLayers等)

    • 编码可分割的最大瓦片行数/列数和切片数
    • 与并行编码性能相关
  • 切片结构(VAConfigAttribEncSliceStructure)

    • 支持的切片组织结构,如灵活宏块排序(FMO)等
  • 宏块信息(VAConfigAttribEncMacroblockInfo)

    • 宏块级别的参数设置和支持情况

3.3 解码专用参数

这些参数特定于视频解码功能:

  • 解码切片模式(VAConfigAttribDecSliceMode)

    • 支持的解码切片处理方式
    • 影响解码器处理效率
  • JPEG解码旋转(VAConfigAttribDecJPEG, VAConfigAttribDecJPEG ROT)

    • JPEG解码时支持的旋转角度(0°、90°、180°、270°)
    • 代码实现:
      if (attrib_list[VAConfigAttribDecJPEG].value != VA_ATTRIB_NOT_SUPPORTED) {
          printf("      VAConfigAttribDecJPEG                     : ");
          print_boolean(attrib_list[VAConfigAttribDecJPEG].value);
          printf("\n");
      }
      if (attrib_list[VAConfigAttribDecJPEG_ROT].value != VA_ATTRIB_NOT_SUPPORTED) {
          printf("      VAConfigAttribDecJPEG_ROT                 : ");
          print_jpeg_rot(attrib_list[VAConfigAttribDecJPEG_ROT].value);
          printf("\n");
      }
      
  • 解码处理类型(VAConfigAttribDecProcessing)

    • 解码处理的类型支持,如是否支持I/P/B帧等

3.4 JPEG编码特定参数

这些参数特定于JPEG编码功能:

  • 算术编码模式(VAConfigAttribEncJPEG, VAConfigAttribEncJPEG_ARITH)

    • 是否支持JPEG算术编码模式
    • 代码实现:
      if (attrib_list[VAConfigAttribEncJPEG].value != VA_ATTRIB_NOT_SUPPORTED) {
          printf("      VAConfigAttribEncJPEG                     : ");
          print_boolean(attrib_list[VAConfigAttribEncJPEG].value);
          printf("\n");
      }
      if (attrib_list[VAConfigAttribEncJPEG_ARITH].value != VA_ATTRIB_NOT_SUPPORTED) {
          printf("      VAConfigAttribEncJPEG_ARITH               : ");
          print_boolean(attrib_list[VAConfigAttribEncJPEG_ARITH].value);
          printf("\n");
      }
      
  • 渐进DCT模式(VAConfigAttribEncJPEG_PROG)

    • 是否支持JPEG渐进式DCT变换
  • 质量范围(VAConfigAttribEncJPEG_QUALITY)

    • JPEG编码的质量参数范围(通常为0-100)
  • 量化方式(VAConfigAttribEncJPEG_QTABLE)

    • 支持的量化方式和量化表设置

3.5 性能和多帧处理参数

这些参数与编码解码性能和多帧处理能力相关:

  • 帧内刷新(VAConfigAttribEncIntraRefresh)

    • 是否支持帧内刷新功能
    • 用于错误恢复和网络适应性
    • 代码实现:
      if (attrib_list[VAConfigAttribEncIntraRefresh].value != VA_ATTRIB_NOT_SUPPORTED) {
          printf("      VAConfigAttribEncIntraRefresh             : VA_ENC_INTRA_REFRESH_MAX %d\n",
                 attrib_list[VAConfigAttribEncIntraRefresh].value);
      }
      
  • ROI支持(VAConfigAttribEncROI)

    • 是否支持感兴趣区域(Region of Interest)编码
    • 允许对视频中重要区域进行更高质量编码
  • 并行码率控制(VAConfigAttribEncParallelRateControl)

    • 是否支持并行码率控制
    • 影响编码性能
  • 动态缩放(VAConfigAttribEncDynamicScaling)

    • 是否支持动态分辨率缩放
    • 用于自适应比特率流
  • FEI功能(VAConfigAttribEncFEIFunctionType)

    • 前端集成(Front End Integration)功能支持情况
    • 如运动估计、去方块滤波等预处理功能
  • MV预测器数量(VAConfigAttribEncMV_PRED)

    • 运动矢量预测器数量
    • 影响编码效率和运动补偿精度

3.6 代码实现解析

show_config_attributes函数是实现-a选项详细输出的核心函数。以下是该函数的部分关键实现:

static void show_config_attributes(VAConfigAttrib *attrib_list, int num_attribs)
{
    int i;

    // 遍历所有配置属性
    for (i = 0; i < num_attribs; i++) {
        switch (attrib_list[i].type) {
            case VAConfigAttribRTFormat:
                // 显示像素格式
                if (attrib_list[i].value != VA_ATTRIB_NOT_SUPPORTED) {
                    printf("      VAConfigAttribRTFormat                    : ");
                    print_rt_format(attrib_list[i].value);
                    printf("\n");
                }
                break;
            
            case VAConfigAttribEncRateControl:
                // 显示码率控制模式
                if (attrib_list[i].value != VA_ATTRIB_NOT_SUPPORTED) {
                    printf("      VAConfigAttribEncRateControl              : ");
                    print_enc_rate_control(attrib_list[i].value);
                    printf("\n");
                }
                break;
            
            // 其他属性类型...
            
            default:
                // 对于不常见的属性类型,以十六进制显示
                printf("      VAConfigAttrib(%d)                         : 0x%x\n",
                       attrib_list[i].type, attrib_list[i].value);
                break;
        }
    }
}

该函数通过switch语句处理不同类型的配置属性,并调用相应的打印函数(如print_rt_formatprint_enc_rate_control等)将属性值转换为人类可读的格式。对于不支持的属性,使用VA_ATTRIB_NOT_SUPPORTED标记进行判断,只显示系统支持的属性。

二、总结

vainfo工具是一个强大的VA-API诊断工具,通过分析其源代码可以深入了解VA-API的工作原理和系统的视频加速能力。main函数实现了完整的VA-API交互流程,包括初始化、查询和资源清理。而show_config_attributes函数则负责将复杂的配置参数转换为人类可读的格式。

-a选项输出的详细参数信息对于开发者了解系统的视频加速能力、选择合适的编解码配置以及进行性能优化都具有重要参考价值。实际输出内容会因系统硬件和驱动程序的不同而有所差异,但基本结构和参数类型保持一致。

三、举例

$ vainfo
libva info: VA-API version 1.14.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/zx_drv_video.so
libva info: Found init function __vaDriverInit_1_0
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.14 (libva 2.4.0)
vainfo: Driver version: ZX_VA
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileMPEG4Simple            : VAEntrypointVLD
      VAProfileMPEG4AdvancedSimple    : VAEntrypointVLD
      <unknown profile>               : VAEntrypointVLD
      <unknown profile>               : VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileH263Baseline           : VAEntrypointVLD
      VAProfileJPEGBaseline           : VAEntrypointVLD
      VAProfileJPEGBaseline           : VAEntrypointEncPicture
      VAProfileNone                   : VAEntrypointVideoProc
      VAProfileHEVCMain               : VAEntrypointVLD
      VAProfileHEVCMain               : VAEntrypointEncSlice
      VAProfileHEVCMain10             : VAEntrypointVLD
      VAProfileHEVCMain10             : VAEntrypointEncSlice
      VAProfileH264MultiviewHigh      : VAEntrypointVLD
      VAProfileH264MultiviewHigh      : VAEntrypointEncSlice
      VAProfileH264StereoHigh         : VAEntrypointVLD
      VAProfileH264StereoHigh         : VAEntrypointEncSlice
      VAProfileVP8Version0_3          : VAEntrypointVLD
      <unknown profile>               : VAEntrypointVLD
      <unknown profile>               : VAEntrypointVLD
      <unknown profile>               : VAEntrypointVLD

1. 解码 (Decoding)
VAEntrypointVLD - Variable Length Decoding

支持的解码格式:MPEG2、MPEG4、H.264、VC1、H.263、JPEG、HEVC、VP8等

  • MPEG2 Simple/Main
  • MPEG4 Simple/AdvancedSimple
  • H.264 Main/High/ConstrainedBaseline/MultiviewHigh/StereoHigh
  • VC1 Simple/Main/Advanced
  • H.263 Baseline
  • JPEG Baseline
  • HEVC Main/Main10
  • VP8

2. 编码 (Encoding)
VAEntrypointEncSlice - 编码切片
VAEntrypointEncPicture - 编码图片

支持的编码格式:H.264、HEVC、JPEG

  • H.264 Main/High/ConstrainedBaseline/MultiviewHigh/StereoHigh
  • HEVC Main/Main10
  • JPEG Baseline

3. 其他
VAProfileNone + VAEntrypointVideoProc

四、补充

EncSlice:用于视频编码,将帧分割成切片并行处理,支持 H.264、HEVC 等
EncPicture:用于图片编码,整帧处理,主要支持 JPEG

1. VA-API 架构

应用程序 → VA-API 接口 → 显卡驱动 → 硬件编码器

VA-API 是英特尔主导的开源视频加速接口,让应用程序能调用显卡的硬件编解码功能。

2. 编码条目点 (Encode Entrypoints)

2.1 VAEntrypointEncSlice - 编码切片

这是最常用的视频编码条目点。

工作原理:

  • 切片(Slice):将一帧图像分割成多个独立编码的单元
  • 并行处理:多个切片可以并行编码,提高效率
  • 错误恢复:某个切片出错不影响其他切片

支持格式:

  • H.264/AVC
  • H.265/HEVC
  • VP9
  • AV1

编码流程:
text

原始帧 → 分割成切片 → 各切片独立编码 → 组合成码流
2.2 VAEntrypointEncPicture - 图片编码

特点:

  • 针对整帧图片进行编码
  • 主要用于静态图片编码
  • 不支持切片分割

支持格式:

  • JPEG 和 MJPEG( Motion JPEG)

3. 与具体编码格式的关系

3.1 H.264 与 EncSlice
# 你的 vainfo 输出显示:
VAProfileH264Main : VAEntrypointEncSlice
VAProfileH264High : VAEntrypointEncSlice

H.264 切片结构:

一帧画面
├── 切片 #1 (独立编码)
├── 切片 #2 (独立编码) 
├── 切片 #3 (独立编码)
└── 切片 #4 (独立编码)

特点:

  • 每个切片包含完整的编码信息
  • 支持帧内预测和帧间预测
  • 适合实时视频编码
3.2 JPEG 与 EncPicture
# 你的 vainfo 输出显示:
VAProfileJPEGBaseline : VAEntrypointEncPicture

JPEG 编码流程:

完整图片 → DCT变换 → 量化 → 熵编码 → JPEG文件

特点:

  • 整张图片一次性处理
  • 基于 DCT 变换的压缩
  • 适合静态图片编码
  1. 技术细节对比
特性 EncSlice EncPicture
处理单元 切片(Slice) 整帧(Picture)
主要用途 视频编码 图片编码
并行性 高(切片级并行) 低(帧级)
延迟 较低 较高
容错性 好(错误隔离) 差(整帧影响)
支持格式 H.264, HEVC, VP9 JPEG, MJPEG
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐