
ArtInChip Luban-Lite SDK Video图层色彩调整实战亮度/对比度/饱和度/色调配置详解最近在用衡山派的ArtInChip平台做视频播放器项目发现播放不同来源的视频时画面色彩效果差异很大。有的视频偏暗有的颜色发灰直接显示效果总是不太理想。好在ArtInChip的显示引擎提供了色彩调整功能可以动态调节亮度、对比度、饱和度和色调让视频画面看起来更舒服。今天咱们就来详细聊聊怎么在Luban-Lite SDK里通过驱动层的API来调整Video图层的显示效果。我会手把手带你理解相关的数据结构学会使用ioctl接口并给出可以直接用的代码示例。如果你是刚开始接触ArtInChip显示开发的工程师这篇教程能帮你快速上手色彩调整功能。1. 色彩调整功能概述1.1 什么是色彩调整简单来说色彩调整就是改变图像显示时的几个关键视觉属性让画面看起来更符合我们的需求。就像咱们看电视时可以按遥控器上的“图像模式”或者手动调节“亮度”、“色彩”一样。ArtInChip平台的显示引擎硬件支持对输出画面进行实时色彩处理。不过需要注意当前Luban-Lite SDK只支持对Video图层进行色彩调整。这里的Video图层特指专门用于显示视频流数据的图层比如从解码器输出的YUV视频数据。UI图层比如用GUI绘制的界面暂时不支持这个功能。通过调整下面这四个参数同一段视频或同一张图片可以呈现出完全不同的视觉效果亮度控制画面的整体明暗程度对比度控制画面最亮和最暗部分的差异程度饱和度控制颜色的鲜艳程度色调控制画面的整体颜色倾向比如偏红、偏蓝1.2 参数范围与默认值这四个参数的调节范围都是0到100而且有一个统一的规则50表示不进行任何调整也就是保持原始画面的效果。当值小于50时减弱对应效果当值等于50时无效果默认状态当值大于50时增强对应效果举个例子如果你觉得画面太暗可以把亮度调到60或70如果觉得颜色太艳有点刺眼可以把饱和度调到40左右。2. 驱动层接口详解要在应用层控制色彩调整我们需要通过Linux标准的ioctl输入输出控制接口与显示驱动进行通信。ArtInChip在驱动层为我们定义好了专用的数据结构和命令。2.1 关键数据结构aicfb_disp_prop所有色彩调整参数都封装在aicfb_disp_prop这个结构体里。咱们先来看看它的定义这个结构体在SDK的头文件bsp/artinchip/include/uapi/artinchip_fb.h中/* * struct aicfb_disp_prop - aicfb display property * * bright: bright in percent, range [0, 100], 50 means no effect * contrast: contrast in percent, range [0, 100], 50 means no effect * saturation: saturation in percent, range [0, 100], 50 means no effect * hue: hue in percent, range [0, 100], 50 means no effect */ struct aicfb_disp_prop { unsigned int bright; // 亮度 unsigned int contrast; // 对比度 unsigned int saturation; // 饱和度 unsigned int hue; // 色调 };这个结构体非常简洁只有四个无符号整型成员分别对应四个色彩属性。每个成员的含义和取值范围如下表所示成员变量中文名称取值范围默认值说明bright亮度[0, 100]5050表示不调节亮度contrast对比度[0, 100]5050表示不调节对比度saturation饱和度[0, 100]5050表示不调节饱和度hue色调[0, 100]5050表示不调节色调注意这些参数的单位是“百分比”但并不是说50就是50%的亮度。实际上50是基准值无调整0到50是减弱效果50到100是增强效果。你可以把它理解为一个相对调整量。2.2 ioctl控制命令有了数据结构我们还需要告诉驱动“我要设置参数”或者“我要读取参数”。这就是通过下面两个宏定义的命令来实现的/** set display property - 设置显示属性 */ #define AICFB_SET_DISP_PROP _IOW(IOC_TYPE_FB, 0x60, struct aicfb_disp_prop) /** get display property - 获取显示属性 */ #define AICFB_GET_DISP_PROP _IOR(IOC_TYPE_FB, 0x61, struct aicfb_disp_prop)这里解释一下_IOW和_IOR_IOW表示这是一个“写”命令我们从用户空间向内核驱动传递数据_IOR表示这是一个“读”命令我们从内核驱动读取数据到用户空间IOC_TYPE_FB是命令的类型标识这里是帧缓冲设备0x60和0x61是具体的命令编号。最后一个参数struct aicfb_disp_prop告诉内核这个命令关联的数据结构是什么。在实际使用中我们不需要关心这些宏的具体实现只需要知道用AICFB_SET_DISP_PROP命令来设置色彩参数用AICFB_GET_DISP_PROP命令来获取当前的色彩参数3. 实战代码示例与操作步骤理论讲完了咱们来看看具体怎么用。我会用一个完整的示例展示如何获取当前设置、修改参数、然后应用新设置。3.1 基础操作流程操作Video图层的色彩调整基本流程就三步打开帧缓冲设备获取文件描述符使用ioctl进行GET或SET操作关闭设备操作完成后下面是完整的代码示例#include stdio.h #include fcntl.h #include unistd.h #include sys/ioctl.h #include artinchip_fb.h // 包含aicfb_disp_prop结构体定义 int main() { int fb; // 帧缓冲设备文件描述符 struct aicfb_disp_prop prop; // 色彩属性结构体 // 1. 打开帧缓冲设备通常为/dev/fb0 fb open(/dev/fb0, O_RDWR); if (fb 0) { perror(打开帧缓冲设备失败); return -1; } // 2. 获取当前的色彩属性设置 if (ioctl(fb, AICFB_GET_DISP_PROP, prop) 0) { perror(获取显示属性失败); close(fb); return -1; } printf(当前设置 - 亮度:%d, 对比度:%d, 饱和度:%d, 色调:%d\n, prop.bright, prop.contrast, prop.saturation, prop.hue); // 3. 修改色彩参数 prop.bright 40; // 降低亮度比默认50暗 prop.contrast 30; // 降低对比度画面更柔和 prop.saturation 45; // 稍微降低饱和度颜色不那么鲜艳 prop.hue 45; // 稍微调整色调 // 4. 应用新的色彩设置 if (ioctl(fb, AICFB_SET_DISP_PROP, prop) 0) { perror(设置显示属性失败); close(fb); return -1; } printf(新设置已应用\n); // 5. 关闭设备 close(fb); return 0; }3.2 使用MPP框架的简化版本在实际的Luban-Lite SDK开发中我们通常会使用MPP多媒体处理平台框架提供的封装接口。MPP框架对底层ioctl进行了封装使用起来更简洁// 假设已经通过mpp_fb_open打开了帧缓冲设备 struct mpp_fb *fb mpp_fb_open(/dev/fb0); struct aicfb_disp_prop prop {50, 50, 50, 50}; // 初始化为默认值 // 获取当前属性 mpp_fb_ioctl(fb, AICFB_GET_DISP_PROP, prop); // 修改参数 prop.bright 40; prop.contrast 30; prop.saturation 45; prop.hue 45; // 设置新属性 mpp_fb_ioctl(fb, AICFB_SET_DISP_PROP, prop);可以看到mpp_fb_ioctl的使用方式和标准ioctl几乎一样只是第一个参数是mpp_fb结构体指针而不是文件描述符。MPP框架内部会处理设备打开、关闭等细节让我们的代码更清晰。3.3 参数调整的实际效果在实际项目中调整这些参数时我有一些经验可以分享亮度调整值小于50画面变暗。适合在暗光环境下使用减少刺眼感。值大于50画面变亮。适合在强光环境下使用提高可视性。我一般从55开始微调每次调整5个单位观察效果。对比度调整值小于50降低对比度黑白反差变小画面显得“灰蒙蒙”的。值大于50提高对比度黑白反差变大画面更“锐利”。调整对比度时要注意太高会丢失暗部细节太低会让画面缺乏层次感。饱和度调整值小于50颜色变淡接近黑白效果。值大于50颜色更鲜艳、更浓郁。这个参数很主观取决于个人喜好和内容类型。自然风景可以调高一点55-60人脸肤色要谨慎太高会显得不自然。色调调整值小于50画面偏绿。值大于50画面偏紫红。这个我一般用得比较少主要用来校正显示设备的色偏。提示调整时最好有参考图像。我通常的做法是准备一张色彩丰富的测试图包含人物肤色、自然景物、灰度阶梯等元素边调整边观察不同区域的效果。4. 命令行工具disp_prop如果你不想写代码或者只是想快速测试一下效果Luban-Lite SDK还提供了一个现成的命令行工具disp_prop。这个工具封装了上面介绍的所有功能可以直接在终端里使用。4.1 基本使用方法打开终端输入disp_prop命令查看帮助$ disp_prop --help典型的用法是直接设置所有参数# 设置亮度60对比度55饱和度58色调50 $ disp_prop -b 60 -c 55 -s 58 -h 50也可以只调整某一个参数其他保持当前值不变# 只调整亮度到65 $ disp_prop -b 65 # 只调整饱和度到45 $ disp_prop -s 454.2 查看当前设置要查看Video图层当前的色彩设置使用-g参数$ disp_prop -g Brightness: 50 Contrast: 50 Saturation: 50 Hue: 50这个功能在调试时特别有用。有时候你可能忘了之前设置了什么值或者想确认设置是否生效用这个命令一看就知道了。4.3 恢复默认设置如果你想快速恢复到默认值全部参数为50可以这样$ disp_prop -b 50 -c 50 -s 50 -h 50或者更简单一点SDK的disp_prop工具可能支持一个重置命令具体看你的SDK版本可以查看帮助文档确认。5. 实际项目中的注意事项在实际项目开发中有几点需要特别注意1. 只对Video图层有效这一点一定要记住色彩调整只作用于Video图层。如果你在UI图层上显示图片调整这些参数是没效果的。有些同事曾经调了半天没反应最后发现是因为操作的不是Video图层。2. 参数是即时生效的当你调用AICFB_SET_DISP_PROP后设置会立即应用到当前显示的视频画面上不需要重启应用或重新初始化显示。这让我们可以实现实时的色彩调节效果比如做一个滑动条让用户自己调节亮度。3. 设置是持久的吗不这些设置不是永久保存的。当关闭显示设备、重启系统、或者切换显示模式时设置会恢复默认值。如果你的应用需要在启动时恢复用户之前的设置需要自己保存这些参数值比如写到配置文件里然后在初始化时重新设置。4. 性能影响色彩调整是在显示引擎的硬件中完成的对CPU占用几乎没影响。不过如果你在频繁地调整参数比如做动画过渡效果要注意ioctl调用本身的开销。我一般会限制调整频率比如每100毫秒检查一次是否需要更新。5. 参数边界检查虽然驱动层应该会检查参数范围但在应用层最好也做一下检查避免传入非法值// 应用层的参数检查 if (bright 100) bright 100; if (contrast 100) contrast 100; if (saturation 100) saturation 100; if (hue 100) hue 100; prop.bright bright; prop.contrast contrast; prop.saturation saturation; prop.hue hue;6. 多图层情况如果你的应用同时显示Video图层和UI图层比如视频播放器上面有控制按钮色彩调整只影响Video图层部分UI图层保持原样。这个特性其实挺好的不会影响用户界面的显示效果。最后分享一个实际项目中的小技巧我通常会在应用启动时读取一次默认值保存起来这样用户即使调乱了也可以提供一个“恢复默认”的按钮。实现起来很简单就是在打开设备后立即调用一次AICFB_GET_DISP_PROP把获取到的值应该是50,50,50,50保存为默认值。色彩调整虽然看起来是个小功能但在提升用户体验上作用很大。特别是针对不同的显示设备LCD屏、OLED屏的显示特性不同和不同的内容类型电影、动画、纪录片的色彩风格不同能够灵活调整显示参数能让你的产品显得更专业、更贴心。