泛全志芯片内核G2D模块sample深究
1. g2d 模块概述
g2d 主要功能:
1)旋转:支持90、180、270旋转;
2)镜像反转:H / V;
3) scale:放缩
4)格式转换:yuv 转 rgb 等,多种格式相互间转换;
5)透明叠加功能:实现两个rgb图片叠加;
6)矩形填充,等诸多功能;
2. g2d 配置
1)源码目录:tina-v853-docker/kernel/linux-4.9/drivers/char/sunxi_g2d
2)make kernel_menuconfig 配置
Device Drivers > Character devices > sunxi g2d driver
按空格键选中【*】
3)Device Tree 设备树配置
sun8iw21p1.dtsi路径:
tina-v853-docker/kernel/linux-4.9/arch/arm/boot/dts/sun8iw21p1.dtsi
g2d: g2d@05410000 { compatible = "allwinner,sunxi-g2d"; reg = <0x0 0x05410000 0x0 0xbffff>; interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk_g2d>; iommus = <&mmu_aw 3 1>; status = "okay"; };
status 要设定为“okay” 状态。
4)重新编译内核
mkernel make -j1 V=s pack
使用烧录工具PhoenixSuit 将路径:tina-v853-docker/out/v851s/lizard/openwrt/v851s_linux_lizard_uart0.img 下的img 镜像烧录到开发板。
5)通过G2D 设备节点,对g2d 进行操作
static int SampleG2d_G2dOpen(SAMPLE_G2D_CTX *p_g2d_ctx) { int ret = 0; p_g2d_ctx->mG2dFd = open("/dev/g2d", O_RDWR, 0); if (p_g2d_ctx->mG2dFd < 0) { aloge("fatal error! open /dev/g2d failed"); ret = -1; } return ret; }
3. 详解 eyesee-mpp 中g2d sample 具体应用
1)eyesee-mpp 中 g2d sample 编译与执行请参考另一篇帖子
链接文本
3)运用 g2d 进行rotation,scale,格式转换
具体实现:将 nv21 格式的1920x1080图转换成rgb888 格式并放缩为640x360 大小。具体用到两个功能,格式转换和放缩。
步骤如下:
1))根据1920x1080 nv21 格式以及 640x360 rgb888 格式申请虚拟地址空间以及转换成物理地址(注意:g2d 转换是在物理地址中完成的)
1920x1080 nv21 格式空间大小(输入文件):
Y 占 19201080 = 2073600 字节
UV 占 19201080 / 2 = 1036800 字节
640x360 rgb888 格式空间大小(输出文件):
RGB 占 6403603 = 691200 字节
另外:虚拟地址转换成物理地址使用如下函数:
g2d_getPhyAddrByVirAddr()
申请虚拟空间并转换成物理空间完整函数如下:
在文件 tina-v853-docker/platform/allwinner/eyesee-mpp/middleware/sun8iw21/sample/sample_g2d/sample_g2d.c/sample_g2d.c 中
static int PrepareFrmBuff(SAMPLE_G2D_CTX *p_g2d_ctx) { SampleG2dConfig *pConfig = NULL; unsigned int size = 0; pConfig = &p_g2d_ctx->mConfigPara; p_g2d_ctx->src_frm_info.frm_width = pConfig->mSrcWidth; p_g2d_ctx->src_frm_info.frm_height = pConfig->mSrcHeight; p_g2d_ctx->dst_frm_info.frm_width = pConfig->mDstWidth; p_g2d_ctx->dst_frm_info.frm_height = pConfig->mDstHeight; size = ALIGN(p_g2d_ctx->src_frm_info.frm_width, 16)*ALIGN(p_g2d_ctx->src_frm_info.frm_height, 16); if(pConfig->mPicFormat == MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420 || pConfig->mPicFormat == MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420) { p_g2d_ctx->src_frm_info.p_vir_addr[0] = (void *)g2d_allocMem(size); if(NULL == p_g2d_ctx->src_frm_info.p_vir_addr[0]) { aloge("malloc_src_frm_y_mem_failed"); return -1; } p_g2d_ctx->src_frm_info.p_vir_addr[1] = (void *)g2d_allocMem(size/2); if(NULL == p_g2d_ctx->src_frm_info.p_vir_addr[1]) { g2d_freeMem(p_g2d_ctx->src_frm_info.p_vir_addr[0]); aloge("malloc_src_frm_c_mem_failed"); return -1; } p_g2d_ctx->src_frm_info.p_phy_addr[0] = (void *)g2d_getPhyAddrByVirAddr(p_g2d_ctx->src_frm_info.p_vir_addr[0]); p_g2d_ctx->src_frm_info.p_phy_addr[1] = (void *)g2d_getPhyAddrByVirAddr(p_g2d_ctx->src_frm_info.p_vir_addr[1]); } if(pConfig->mDstPicFormat == MM_PIXEL_FORMAT_RGB_888) { size = p_g2d_ctx->dst_frm_info.frm_width * p_g2d_ctx->dst_frm_info.frm_height * 3; p_g2d_ctx->dst_frm_info.p_vir_addr[0] = (void *)g2d_allocMem(size); if(NULL == p_g2d_ctx->dst_frm_info.p_vir_addr[0]) { if(p_g2d_ctx->src_frm_info.p_vir_addr[0] != NULL) { g2d_freeMem(p_g2d_ctx->src_frm_info.p_vir_addr[0]); } if(p_g2d_ctx->src_frm_info.p_vir_addr[1] != NULL) { g2d_freeMem(p_g2d_ctx->src_frm_info.p_vir_addr[1]); } aloge("malloc_dst_frm_y_mem_failed"); return -1; } p_g2d_ctx->dst_frm_info.p_phy_addr[0] = (void *)g2d_getPhyAddrByVirAddr(p_g2d_ctx->dst_frm_info.p_vir_addr[0]); } return 0; }
2))通过fopen 传菜间两个文件句柄,fd_in fd_out 用来操作输入输出两个文件资源
p_g2d_ctx->fd_in = fopen(p_g2d_ctx->mConfigPara.SrcFile,"r"); if(NULL == p_g2d_ctx->fd_in) { aloge("open src file failed"); ret = -1; goto _err2; } fseek(p_g2d_ctx->fd_in, 0, SEEK_SET); p_g2d_ctx->fd_out = fopen(p_g2d_ctx->mConfigPara.DstFile, "wb"); if (NULL == p_g2d_ctx->fd_out) { aloge("open out file failed"); ret = -1; goto _err2; } fseek(p_g2d_ctx->fd_out, 0, SEEK_SET);
3))读出 1920x1080 nv21 图资放入 虚拟空间
read_len = p_g2d_ctx->src_frm_info.frm_width * p_g2d_ctx->src_frm_info.frm_height; if(pConfig->mPicFormat == MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420|| pConfig->mPicFormat == MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420) { size1 = fread(p_g2d_ctx->src_frm_info.p_vir_addr[0] , 1, read_len, p_g2d_ctx->fd_in); if(size1 != read_len) { aloge("read_y_data_frm_src_file_invalid"); } size2 = fread(p_g2d_ctx->src_frm_info.p_vir_addr[1], 1, read_len /2, p_g2d_ctx->fd_in); if(size2 != read_len/2) { aloge("read_c_data_frm_src_file_invalid"); } fclose(p_g2d_ctx->fd_in); g2d_flushCache((void *)p_g2d_ctx->src_frm_info.p_vir_addr[0], read_len); g2d_flushCache((void *)p_g2d_ctx->src_frm_info.p_vir_addr[1], read_len/2); }
4))打开g2d 初始化,并开始转换
ret = SampleG2d_G2dOpen(p_g2d_ctx); if (ret < 0) { aloge("fatal error! open /dev/g2d fail!"); goto _err2; } ret = SampleG2d_G2dConvert(p_g2d_ctx); if (ret < 0) { aloge("fatal error! g2d convert fail!"); goto _close_g2d; } //具体转化函数: static int SampleG2d_G2dConvert_scale(SAMPLE_G2D_CTX *p_g2d_ctx) { int ret = 0; g2d_blt_h blit; g2d_fmt_enh eSrcFormat, eDstFormat; SampleG2dConfig *pConfig = NULL; pConfig = &p_g2d_ctx->mConfigPara; ret = convert_PIXEL_FORMAT_E_to_g2d_fmt_enh(pConfig->mPicFormat, &eSrcFormat); if(ret!=SUCCESS) { aloge("fatal error! src pixel format[0x%x] is invalid!", pConfig->mPicFormat); return -1; } ret = convert_PIXEL_FORMAT_E_to_g2d_fmt_enh(pConfig->mDstPicFormat, &eDstFormat); if(ret!=SUCCESS) { aloge("fatal error! dst pixel format[0x%x] is invalid!", pConfig->mPicFormat); return -1; } //config blit memset(&blit, 0, sizeof(g2d_blt_h)); if(0 != pConfig->mDstRotate) { aloge("fatal_err: rotation can't be performed when do scaling"); } blit.flag_h = G2D_BLT_NONE_H; // angle rotation used // switch(pConfig->mDstRotate) // { // case 0: // blit.flag_h = G2D_BLT_NONE_H; //G2D_ROT_0, G2D_BLT_NONE_H // break; // case 90: // blit.flag_h = G2D_ROT_90; // break; // case 180: // blit.flag_h = G2D_ROT_180; // break; // case 270: // blit.flag_h = G2D_ROT_270; // break; // default: // aloge("fatal error! rotation[%d] is invalid!", pConfig->mDstRotate); // blit.flag_h = G2D_BLT_NONE_H; // break; // } //blit.src_image_h.bbuff = 1; //blit.src_image_h.color = 0xff; blit.src_image_h.format = eSrcFormat; blit.src_image_h.laddr[0] = (unsigned int)p_g2d_ctx->src_frm_info.p_phy_addr[0]; blit.src_image_h.laddr[1] = (unsigned int)p_g2d_ctx->src_frm_info.p_phy_addr[1]; blit.src_image_h.laddr[2] = (unsigned int)p_g2d_ctx->src_frm_info.p_phy_addr[2]; //blit.src_image_h.haddr[] = blit.src_image_h.width = p_g2d_ctx->src_frm_info.frm_width; blit.src_image_h.height = p_g2d_ctx->src_frm_info.frm_height; blit.src_image_h.align[0] = 0; blit.src_image_h.align[1] = 0; blit.src_image_h.align[2] = 0; blit.src_image_h.clip_rect.x = pConfig->mSrcRectX; blit.src_image_h.clip_rect.y = pConfig->mSrcRectY; blit.src_image_h.clip_rect.w = pConfig->mSrcRectW; blit.src_image_h.clip_rect.h = pConfig->mSrcRectH; blit.src_image_h.gamut = G2D_BT601; blit.src_image_h.bpremul = 0; //blit.src_image_h.alpha = 0xff; blit.src_image_h.mode = G2D_PIXEL_ALPHA; //G2D_PIXEL_ALPHA, G2D_GLOBAL_ALPHA blit.src_image_h.fd = -1; blit.src_image_h.use_phy_addr = 1; //blit.dst_image_h.bbuff = 1; //blit.dst_image_h.color = 0xff; blit.dst_image_h.format = eDstFormat; blit.dst_image_h.laddr[0] = (unsigned int)p_g2d_ctx->dst_frm_info.p_phy_addr[0]; blit.dst_image_h.laddr[1] = (unsigned int)p_g2d_ctx->dst_frm_info.p_phy_addr[1]; blit.dst_image_h.laddr[2] = (unsigned int)p_g2d_ctx->dst_frm_info.p_phy_addr[2]; //blit.dst_image_h.haddr[] = blit.dst_image_h.width = p_g2d_ctx->dst_frm_info.frm_width; blit.dst_image_h.height = p_g2d_ctx->dst_frm_info.frm_height; blit.dst_image_h.align[0] = 0; blit.dst_image_h.align[1] = 0; blit.dst_image_h.align[2] = 0; blit.dst_image_h.clip_rect.x = pConfig->mDstRectX; blit.dst_image_h.clip_rect.y = pConfig->mDstRectY; blit.dst_image_h.clip_rect.w = pConfig->mDstRectW; blit.dst_image_h.clip_rect.h = pConfig->mDstRectH; blit.dst_image_h.gamut = G2D_BT601; blit.dst_image_h.bpremul = 0; //blit.dst_image_h.alpha = 0xff; blit.dst_image_h.mode = G2D_PIXEL_ALPHA; //G2D_PIXEL_ALPHA, G2D_GLOBAL_ALPHA blit.dst_image_h.fd = -1; blit.dst_image_h.use_phy_addr = 1; ret = ioctl(p_g2d_ctx->mG2dFd, G2D_CMD_BITBLT_H, (unsigned long)&blit); if(ret < 0) { aloge("fatal error! bit-block(image) transfer failed[%d]", ret); system("cd /sys/class/sunxi_dump;echo 0x14A8000,0x14A8100 > dump;cat dump"); } return ret; }
5))转化完成后将640x360 rgb888 图资通过fd_out句柄存储起来
if(pConfig->mDstPicFormat == MM_PIXEL_FORMAT_RGB_888) { out_len = p_g2d_ctx->dst_frm_info.frm_width * p_g2d_ctx->dst_frm_info.frm_height *3; g2d_flushCache((void *)p_g2d_ctx->dst_frm_info.p_vir_addr[0], out_len); fwrite(p_g2d_ctx->dst_frm_info.p_vir_addr[0], 1, out_len, p_g2d_ctx->fd_out); }
4. 总结转化步骤
通过步骤3中的模块化分析,可以看出g2d 转化大概分为一下步骤:
1)为打开 iomen 初始化;
2)为src以及dst图资申请虚拟地址空间并转换成物理地址空间;
3)将src图资放入虚拟地址空间,然后自动映射到物理地址空间;
4)打开g2d 设备节点进行转换(最重要的一环,可以通过手册分析具体怎么转换的);
5)将转换好的dst图资保存起来;

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
漫谈前端自动化测试演进之路及测试工具分析
作者:京东零售 杜兴文 随着前端技术的不断发展和应用程序的日益复杂,前端自动化测试也在不断演进。 Web 前端 UI 自动化测试发展史可以追溯到 2000 年,当时最早的 Web 应用程序越来越复杂,开发人员开始使用自动化测试工具来确保应用程序的正确性和可靠性。 在早期,自动化测试是通过使用脚本或脚本来模拟用户的操作来完成的。这些测试工具通常基于 JavaScript 编写,并且需要对 Web 应用程序的交互方式进行深入了解。 随着 Web 应用程序变得越来越复杂,自动化测试的需求也越来越高。2005 年,Selenium 开始流行,它是一种基于 Java 的自动化测试框架,可以用于模拟用户操作并进行 Web 应用程序的自动化测试。 Selenium 和其他自动化测试工具的出现使得 Web 前端 UI 自动化测试变得更加容易和高效。随着 Web 应用程序的不断演变,自动化测试工具也在不断更新和发展。如今,自动化测试已经成为 Web 应用程序开发过程中不可或缺的一部分,它们可以帮助开发人员更快地发现和修复错误,提高应用程序的性能和可靠性。 下面是前端自动化测试经历的阶段: 1. 手动测试...
- 下一篇
缓存与数据库双写一致性几种策略分析
作者:京东零售于泷 一、背景 在高并发场景中,为防止大量请求直接访问数据库,缓解数据库压力,常用的方式一般会增加缓存层起到缓冲作用,减少数据库压力。引入缓存,就会涉及到缓存与数据库中数据如何保持一致性问题,本文将对几种缓存与数据库保证数据一致性的使用方式进行分析。为保证高并发性能,以下分析场景不考虑执行的原子性及加锁等强一致性要求的场景,仅追求最终一致性。 二、读取过程 • 读缓存 • 如果缓存里没有值,那就读取数据库的值 • 同时把这个值写进缓存中 三、更新过程 更新操作有多种策略,各有优劣,主要针对此场景进行分析 策略1:先更新db,再删除缓存(常用的Cache-Aside Pattern旁路缓存) 问题: 1.如果更新db成功,删缓存失败,将导致数据不一致 2.极端场景,请求A读,B写 1)此时缓存刚好失效 2)A查库得到旧值 3)B更新DB成功 4)B删除缓存 5)A将查到的旧值更新到缓存中 此场景的发生需要步骤2)查db 始终慢于 3)的更新db,才能导致4)先于5)执行,通常db的查询是要快于写入的,所以此极端场景的产生过于严格,不易发生 策略2:先更新db...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8编译安装MySQL8.0.19
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7安装Docker,走上虚拟化容器引擎之路