详解全志V85x内G2D模块实现图片格式步骤方法

全志在线 2023-04-18 17:17

G2D模块概述

作者@chhjnavy

原文:https://bbs.aw-ol.com/topic/3291/


G2D主要功能:
1)旋转:支持90、180、270旋转;
2)scale:放缩;

3)镜像反转:H / V;

4)透明叠加:实现两个rgb图片叠加;

5)格式转换:yuv转rgb等多种格式相互间转换;

6)矩形填充,等诸多功能;



G2D配置


源码目录

  • tina-v853-docker/kernel/linux-4.9/drivers/char/sunxi_g2d


make kernel_menuconfig 配置

  • Device Drivers > Character devices > sunxi g2d driver


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 = 89 IRQ_TYPE_LEVEL_HIGH>;      clocks = <&clk_g2d>;      iommus = <&mmu_aw 3 1>;      status = "okay";    };


注:status 要设定为“okay” 状态。


重新编译内核

使用烧录工具PhoenixSuit 将编译打包好的img镜像烧录到开发板。


adb shell 打开控制终端查看设备节点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;}


G2D sample具体应用


G2D sample目录


进行rotation,scale,格式转换

具体实现:将 nv21 格式的1920x1080图转换成rgb888 格式并放缩为640x360 大小。具体用到两个功能,格式转换和放缩。


首先根据1920x1080 nv21 格式以及 640x360 rgb888 格式申请虚拟地址空间以及转换成物理地址(注意:g2d 转换是在物理地址中完成的)


1920x1080 nv21 格式空间大小(输入文件):

  • Y 占 19201080 = 2073600 字节

  • UV 占 19201080 / 2 = 1036800 字节


640x360 rgb888 格式空间大小(输出文件):

  • RGB 占 6403603 = 691200 字节


另外:虚拟地址转换成物理地址使用如下函数:

g2d_getPhyAddrByVirAddr()


申请虚拟空间并转换成物理空间完整函数如下:

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; }


通过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);


读出 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);        }


打开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;}


转化完成后将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);        }


转化步骤总结


通过步骤3中的模块化分析,可以看出g2d 转化大概分为一下步骤:

  1. 为打开 iomen 初始化;

  2. 为src以及dst图资申请虚拟地址空间并转换成物理地址空间;

  3. 将src图资放入虚拟地址空间,然后自动映射到物理地址空间;

  4. 打开g2d 设备节点进行转换(最重要的一环,可以通过手册分析具体怎么转换的);

  5. 将转换好的dst图资保存起来;


-End-

本文转载自:https://bbs.aw-ol.com/topic/3291/

评论 (0)
  •   高海拔区域勤务与装备保障调度系统平台解析   北京华盛恒辉高海拔区域勤务与装备保障调度系统平台专为高海拔特殊地理环境打造,致力于攻克装备适应、人员健康保障、物资运输及应急响应等难题。以下从核心功能、技术特点、应用场景及发展趋势展开全面解读。   应用案例   目前,已有多个高海拔区域勤务与装备保障调度系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润高海拔区域勤务与装备保障调度系统。这些成功案例为高海拔区域勤务与装备保障调度系统的推广和应用提供了有力支持。   一、核心
    华盛恒辉l58ll334744 2025-04-24 10:13 60浏览
  • 故障现象一辆2016款奔驰C200L车,搭载274 920发动机,累计行驶里程约为13万km。该车组合仪表上的防侧滑故障灯、转向助力故障灯、安全气囊故障灯等偶尔异常点亮,且此时将挡位置于R挡,中控显示屏提示“后视摄像头不可用”,无法显示倒车影像。 故障诊断用故障检测仪检测,发现多个控制单元中均存储有通信类故障代码(图1),其中故障代码“U015587 与仪表盘的通信存在故障。信息缺失”出现的频次较高。 图1 存储的故障代码1而组合仪表中存储有故障代码“U006488 与用户界
    虹科Pico汽车示波器 2025-04-23 11:22 89浏览
  • 前言本文主要演示基于TL3576-MiniEVM评估板HDMI OUT、DP 1.4和MIPI的多屏同显、异显方案,适用开发环境如下。Windows开发环境:Windows 7 64bit、Windows 10 64bitLinux开发环境:VMware16.2.5、Ubuntu22.04.5 64bitU-Boot:U-Boot-2017.09Kernel:Linux-6.1.115LinuxSDK:LinuxSDK-[版本号](基于rk3576_linux6.1_release_v
    Tronlong 2025-04-23 13:59 123浏览
  •   复杂电磁环境模拟系统平台解析   一、系统概述   北京华盛恒辉复杂电磁环境模拟系统平台是用于还原真实战场或特定场景电磁环境的综合性技术平台。该平台借助软硬件协同运作,能够产生多源、多频段、多体制的电磁信号,并融合空间、时间、频谱等参数,构建高逼真度的电磁环境,为电子对抗、通信、雷达等系统的研发、测试、训练及评估工作提供重要支持。   应用案例   目前,已有多个复杂电磁环境模拟系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润复杂电磁环境模拟系统。这些成功案例为复杂电
    华盛恒辉l58ll334744 2025-04-23 10:29 176浏览
  •   陆地边防事件紧急处置系统平台解析   北京华盛恒辉陆地边防事件紧急处置系统平台是整合监测、预警、指挥等功能的智能化综合系统,致力于增强边防安全管控能力,快速响应各类突发事件。以下从系统架构、核心功能、技术支撑、应用场景及发展趋势展开全面解读。   应用案例   目前,已有多个陆地边防事件紧急处置系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润陆地边防事件紧急处置系统。这些成功案例为陆地边防事件紧急处置系统的推广和应用提供了有力支持。   一、系统架构   感知层:部
    华盛恒辉l58ll334744 2025-04-23 11:22 121浏览
  •   电磁频谱数据综合管理平台系统解析   一、系统定义与目标   北京华盛恒辉电磁频谱数据综合管理平台融合无线传感器、软件定义电台等前沿技术,是实现无线电频谱资源全流程管理的复杂系统。其核心目标包括:优化频谱资源配置,满足多元通信需求;运用动态管理与频谱共享技术,提升资源利用效率;强化频谱安全监管,杜绝非法占用与干扰;为电子战提供频谱监测分析支持,辅助作战决策。   应用案例   目前,已有多个电磁频谱数据综合管理平台在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润电磁频谱数
    华盛恒辉l58ll334744 2025-04-23 16:27 173浏览
  • 一、行业背景与市场需求高血压作为全球发病率最高的慢性病之一,其早期监测与管理已成为公共卫生领域的重要课题。世界卫生组织数据显示,全球超13亿人受高血压困扰,且患者群体呈现年轻化趋势。传统血压计因功能单一、数据孤立等缺陷,难以满足现代健康管理的需求。在此背景下,集语音播报、蓝牙传输、电量检测于一体的智能血压计应运而生,通过技术创新实现“测量-分析-管理”全流程智能化,成为慢性病管理的核心终端设备。二、技术架构与核心功能智能血压计以电子血压测量技术为基础,融合物联网、AI算法及语音交互技术,构建起多
    广州唯创电子 2025-04-23 09:06 157浏览
  •   后勤实验仿真系统平台深度解析   北京华盛恒辉后勤实验仿真系统平台依托计算机仿真技术,是对后勤保障全流程进行模拟、分析与优化的综合性工具。通过搭建虚拟场景,模拟资源调配、物资运输等环节,为后勤决策提供数据支撑,广泛应用于军事、应急管理等领域。   应用案例   目前,已有多个后勤实验仿真系统平台在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润后勤实验仿真系统平台。这些成功案例为后勤实验仿真系统平台的推广和应用提供了有力支持。   一、核心功能   (一)后勤资源模拟
    华盛恒辉l58ll334744 2025-04-23 15:39 151浏览
  • 一、技术背景与市场机遇在智能家居高速发展的今天,用户对家电设备的安全性、智能化及能效表现提出更高要求。传统取暖器因缺乏智能感知功能,存在能源浪费、安全隐患等痛点。WTL580-C01微波雷达感应模块的诞生,为取暖设备智能化升级提供了创新解决方案。该模块凭借微波雷达技术优势,在精准测距、环境适应、能耗控制等方面实现突破,成为智能取暖器领域的核心技术组件。二、核心技术原理本模块采用多普勒效应微波雷达技术,通过24GHz高频微波信号的发射-接收机制,实现毫米级动作识别和精准测距。当人体进入4-5米有效
    广州唯创电子 2025-04-23 08:41 149浏览
  •   有效样本分析决策系统平台全面解析   一、引言   北京华盛恒辉有效样本分析决策系统在当今数据驱动的时代,企业、科研机构等面临着海量数据的处理与分析挑战。有效样本分析决策系统平台应运而生,它通过对样本数据的精准分析,为决策提供有力支持,成为提升决策质量和效率的关键工具。   应用案例   目前,已有多个有效样本分析决策系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润有效样本分析决策系统。这些成功案例为有效样本分析决策系统的推广和应用提供了有力支持。   二、平台概述
    华盛恒辉l58ll334744 2025-04-24 11:13 58浏览
  •   陆地装备体系论证与评估综合平台系统解析   北京华盛恒辉陆地装备体系论证与评估综合平台系统是契合现代军事需求而生的专业系统,借助科学化、智能化手段,实现对陆地装备体系的全方位论证与评估,为军事决策和装备发展提供关键支撑。以下从功能、技术、应用及展望展开分析。   应用案例   目前,已有多个陆地装备体系论证与评估综合平台在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润陆地装备体系论证与评估综合平台。这些成功案例为陆地装备体系论证与评估综合平台的推广和应用提供了有力支持。
    华盛恒辉l58ll334744 2025-04-24 10:53 54浏览
  •   无人机结构仿真与部件拆解分析系统平台解析   北京华盛恒辉无人机结构仿真与部件拆解分析系统无人机技术快速发展的当下,结构仿真与部件拆解分析系统平台成为无人机研发测试的核心工具,在优化设计、提升性能、降低成本等方面发挥关键作用。以下从功能、架构、应用、优势及趋势展开解析。   应用案例   目前,已有多个无人机结构仿真与部件拆解分析系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润无人机结构仿真与部件拆解分析系统。这些成功案例为无人机结构仿真与部件拆解分析系统的推广和应用提
    华盛恒辉l58ll334744 2025-04-23 15:00 183浏览
我要评论
0
1
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦