全志V851s、V853内g2d模块sample深究

news2025/1/21 1:02:04

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 镜像烧录到开发板。

adb shell 打开控制终端查看设备节点G2D:
在这里插入图片描述

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 编译与执行请参考另一篇帖子
链接文本

2)g2d sample 目录
在这里插入图片描述

3)运用 g2d 进行rotation,scale,格式转换
具体实现:将 nv21 格式的1920x1080图转换成rgb888 格式并放缩为640x360 大小。具体用到两个功能,格式转换和放缩。
步骤如下:
1))根据1920x1080 nv21 格式以及 640x360 rgb888 格式申请虚拟地址空间以及转换成物理地址(注意:g2d 转换是在物理地址中完成的)

1920x1080 nv21 格式空间大小(输入文件):
在这里插入图片描述

Y 占 19201080 = 2073600 字节
UV 占 1920
1080 / 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图资保存起来;

V853开发文档手册:https://bbs.aw-ol.com/topic/3291/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/434559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python学习——缺失值、重复值处理、排序及替换

文章目录 1 缺失值处理1.1 查看缺失值 df.isnull()1.2 统计缺失值 df.isnull().sum()1.3 删除缺失值 df.drop()1.4 填充缺失值 df.fillna()1.4.1 固定值填充 df.fillna(value)1.4.2 线性插值填充 df.fillna(df.interpolate()) 2 重复值处理2.1 查看重复值 df.duplicated()2.2 筛…

最佳实践:Android应用中的网络请求和数据缓存

最佳实践&#xff1a;Android应用中的网络请求和数据缓存 网络请求在Android应用中的重要性 在现代移动应用中&#xff0c;网络请求扮演着重要的角色&#xff0c;涉及到数据的获取、上传、更新等功能。网络请求在Android应用中具有关键地位&#xff0c;对于提供优秀的用户体验和…

如何使用山海鲸可视化绘制堆叠双轴图?

简介 堆叠双轴图是一种数据可视化图表类型&#xff0c;它结合了堆叠柱状图和双轴图的特点&#xff0c;将两个或更多个数据系列以不同的颜色或图案堆叠在一起&#xff0c;同时使用两个垂直轴来表示不同的数据范围&#xff0c;以显示它们之间的关系和趋势。其中一个轴通常代表数…

一个实例讲解如何使用BP神经网络(附代码)

本站原创文章&#xff0c;转载请说明来自《老饼讲解-BP神经网络》bp.bbbdata.com BP神经网络是一个广泛应用的模型&#xff0c; 本文以一个实例作为主线&#xff0c;面向初学者讲解如何构建和使用一个BP神经网络 帮助没接触进BP神经网络的初学者&#xff0c;快速上手BP神经网络…

传统机器学习(四)聚类算法DBSCAN

传统机器学习(四)聚类算法DBSCAN 1.1 算法概述 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff0c;具有噪声的基于密度的聚类方法&#xff09;是一种基于密度的空间聚类算法。 该算法将具有足够密度的区域划分为簇&#xff0c;并在…

【C++学习】类和对象--对象特性(2)

静态成员 静态成员就是在成员变量和成员函数前加上关键字static&#xff0c;称为静态成员。 静态成员变量&#xff1a; 所有对象共享同一份数据 在编译阶段分配内存 类内声明&#xff0c;类外初始化 静态成员函数&#xff1a; 所有对象共享同一个函数 静态成员函数只能访问静态…

MyBatis小技巧

一、MyBatis中接口代理机制及使用 我们不难发现&#xff0c;以前编写dao/mapper实现类中的方法代码很固定&#xff0c;基本上就是一行代码&#xff0c;通过SqlSession对象调用insert、delete、update、select等方法&#xff0c;这个类中的方法没有任何业务逻辑&#xff0c;既然…

【Cadence】 ADS Dynamic Link使用教程

ADS Dynamic Link使用教程 1.新建一个Cadence Schematic2.打开ADS3.在ADS新建Schematic4.加入控件OPTIONS5.加入Netlist6.仿真测试7.写在最后 1.新建一个Cadence Schematic 随便搭了一个Cascode 注意这个时候不要新建symbol 2.打开ADS 3.在ADS新建Schematic 选择对应的Cade…

BI技巧丨计算组环形图

当我们使用Power BI时&#xff0c;会发现其内置了许多可视化组件&#xff0c;这些组件可以帮我们快速地创建各种类型的报表和仪表板&#xff0c;这是非常方便的。但是&#xff0c;我们也会发现&#xff0c;有些组件的细节功能并不是很完善&#xff0c;这就导致了我们在平常使用…

解决 mapper.xml 文件的 resultType 爆红问题:Cannot resolve symbol ‘xxx‘

解决mapper.xml文件的resultType爆红问题&#xff1a;Cannot resolve symbol xxx 1.问题描述2.问题分析3.问题解决3.1 配置注解&#xff08;推荐&#xff09;3.2 配置全类名3.3 删除插件 4.事件感悟 系统&#xff1a;Win10 JDK&#xff1a;1.8.0_333 IDEA&#xff1a;2022.2.4 …

【C++】Qt环境下的五子棋小程序

实现要求 这个程序是一个基于Qt的五子棋游戏&#xff0c;实现了人机对战和双人对战两种游戏模式&#xff0c;提供了基本的棋谱记录和游戏音效功能。程序采用了MVC模式&#xff0c;将数据与界面分离&#xff0c;实现了代码的模块化和可扩展性。主要构建包括三个文件&#xff0c…

Java - 数据结构,哈希表

一、概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须要经过关键码的多次比较。顺序查找时间复杂度为O(N)&#xff0c;平衡树中为树的高度&#xff0c;即O( )&#xff0c;搜索的效率取决于搜…

Ambari【部署 01】最新版本ambari-2.7.7下载编译打包安装使用(踩坑实录)

Ambari 官网 本次安装的为当前最新版本 2.7.7 文档 。 1.环境及准备 1.1 环境 # 系统 [roottcloud ~]# cat /etc/centos-release CentOS Linux release 7.9.2009 (Core) # JDK [roottcloud ~]# java -version java version "1.8.0_241" Java(TM) SE Runtime Envir…

java模板/策略模式打怪兽

模板&策略模式 实现姿势 我们会从简单到复杂&#xff0c;讲解代码正确的实现姿势&#xff0c;分别为最 Low 方式、常规方式、模板模式和策略模式。 最 Low 方式 假如现在有 3 个奥特曼&#xff0c;都喜欢 “训练&#xff0c;飞翔&#xff0c;打怪兽” public class OldTig…

jsp+java自行车租赁租借和买卖系统

自行车租借和买卖系统 系统包括四个模块。1&#xff0c;系统模块&#xff0c;2&#xff0c;车辆管理模块&#xff0c;3.租借车管理模块&#xff0c;4&#xff0c;买卖车管理模块。 1&#xff0c;系统模块包括: 连接数据库&#xff0c;工作人员登录&#xff0c;退出。 2&#…

《类和对象》(中篇)

本文主要介绍类里面的六大默认成员函数 文章目录 前言类的6个默认成员函数1、构造函数1.1 概念1.2 特性 2、析构函数2.1 概念2.2 特性 3 、拷贝构造函数3.1 概念3.2 特性3.3 使用场景 4、运算符重载4.1 规则4.2 赋值运算符重载 5、const 成员6、取地址与const取地址操作符重载总…

Shiro安全框架简介

一、权限管理 1.1 什么是权限管理 基本上只要涉及到用户参数的系统都要进行权限管理&#xff0c;使用权限管理实现了对用户访问系统的控制&#xff0c;不同的用户访问不同的资源。按照安全规则或者安全策略控制用户访问资源&#xff0c;而且只能访问被授权的资源 权限管理包括认…

学成在线笔记+踩坑(1)——项目思路、架构、父工程和基础工程,Gogs使用

【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线牛客面试题 目录 简历-技术架构 项目预览 后台页面 课程管理 媒资管理页面上传视频 新增课程 课程管理页提交审核 审核员审核后发布课程 前台页面 主页 验证码登录…

uniapp系列-超详细教你在uni-app+vue3里通过web-view组件传递信息打开H5页面写入localstorage并解决兼容性

web-view是什么 web-view 是一个 web 浏览器组件&#xff0c;可以用来承载网页的容器&#xff0c;会自动铺满整个页面&#xff08;nvue 使用需要手动指定宽高&#xff09;。点击这里直达官网文档点击这里下载我的代码demo本文最下面还有一些常见或者奇怪问题解决方案哦~ 为什…

GMRES算法及Matlab程序

关于GMRES的总结 一些理论以及代码 首先是我们要解决的问题&#xff0c;也就是最常见的问题&#xff0c;即求解 A x b Axb Axb Galerkin条件 krylov子空间 我们所做的GMRES实际上就是在Galerkin条件的扩张下&#xff0c;n o r m ( r ) normnorm不断减小的一个过程。这也是…