vainfo-源码分析
vainfo-源码分析
- 一、vainfo工具概述
- 1. vainfo工具输出格式详解
- 1.1 基本输出示例
- 1.2 详细输出示例(使用-a选项)
- 2. main函数流程和功能分析
- 2.1 核心代码解析
- 2.2 执行流程详解
- 3. -a选项输出的编解码参数功能
- 3.1 基本视频格式参数
- 3.2 编码专用参数
- 3.3 解码专用参数
- 3.4 JPEG编码特定参数
- 3.5 性能和多帧处理参数
- 3.6 代码实现解析
- 二、总结
一、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会显示以下信息:
- VA-API版本和驱动版本信息
- 支持的编解码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 entrypointsVAProfileMPEG2Simple : VAEntrypointVLDVAProfileMPEG2Main : VAEntrypointVLDVAProfileH264ConstrainedBaseline: VAEntrypointVLDVAProfileH264Main : VAEntrypointVLDVAProfileH264High : 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 : VAEntrypointEncSliceVAConfigAttribRTFormat : VA_RT_FORMAT_YUV420VAConfigAttribEncRateControl : VA_RC_CBR | VA_RC_VBRVAConfigAttribEncIntraRefresh : VA_ENC_INTRA_REFRESH_MAX 1VAConfigAttribEncMaxRefFrames : 16VAConfigAttribEncMaxSlices : 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);// 遍历所有profilefor (i = 0; i < num_profiles; i++) {// 查询每个profile支持的entrypointva_status = vaQueryConfigEntrypoints(display, profile_list[i], &entrypoint_list, &num_entrypoints);CHECK_VASTATUS("vaQueryConfigEntrypoints", va_status);// 遍历所有entrypointfor (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函数的执行流程可以分为以下几个关键步骤:
-
初始化与参数解析
- 调用
parse_args
函数解析命令行参数 - 设置
show_all_opt
全局变量,控制是否显示详细配置属性 - 支持的命令行选项包括
--help
和-a/--all
- 调用
-
VA-API显示设备初始化
- 调用
va_open_display
函数初始化VA显示设备 - 调用
vaInitialize
函数初始化VA-API并获取版本信息 - 使用
CHECK_VASTATUS
宏检查VA函数调用的返回状态
- 调用
-
版本信息显示
- 打印VA-API版本号(运行时版本和编译时版本)
- 打印驱动程序版本信息
- 这些信息由
vaQueryVendorString
函数获取
-
配置查询
- 调用
vaQueryConfigProfiles
函数获取所有支持的profile - 对每个profile,调用
vaQueryConfigEntrypoints
函数获取其支持的entrypoint - 这些信息通过动态内存分配存储在
profile_list
和entrypoint_list
中
- 调用
-
输出模式
- 默认模式:仅显示支持的profile和entrypoint组合,使用格式化输出
- 详细模式(-a选项):对于每个profile/entrypoint组合:
- 调用
vaCreateConfig
创建配置 - 调用
vaQueryConfigAttributes
查询配置属性 - 调用
show_config_attributes
函数显示详细属性信息 - 调用
vaDestroyConfig
销毁配置
- 调用
-
资源清理
- 释放动态分配的内存
- 调用
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_format
、print_enc_rate_control
等)将属性值转换为人类可读的格式。对于不支持的属性,使用VA_ATTRIB_NOT_SUPPORTED
标记进行判断,只显示系统支持的属性。
二、总结
vainfo工具是一个强大的VA-API诊断工具,通过分析其源代码可以深入了解VA-API的工作原理和系统的视频加速能力。main函数实现了完整的VA-API交互流程,包括初始化、查询和资源清理。而show_config_attributes函数则负责将复杂的配置参数转换为人类可读的格式。
-a选项输出的详细参数信息对于开发者了解系统的视频加速能力、选择合适的编解码配置以及进行性能优化都具有重要参考价值。实际输出内容会因系统硬件和驱动程序的不同而有所差异,但基本结构和参数类型保持一致。