0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

全志V85x內(nèi)G2D模塊實(shí)現(xiàn)圖片格式步驟方法

全志在線(xiàn) ? 來(lái)源:chhjnavy ? 作者:chhjnavy ? 2023-04-19 09:41 ? 次閱讀

G2D主要功能:

1)旋轉(zhuǎn):支持90、180、270旋轉(zhuǎn);

2)scale:放縮;

3)鏡像反轉(zhuǎn):H / V;

4)透明疊加:實(shí)現(xiàn)兩個(gè)rgb圖片疊加;

5)格式轉(zhuǎn)換:yuv轉(zhuǎn)rgb等多種格式相互間轉(zhuǎn)換;

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

G2D配置

源碼目錄

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

make kernel_menuconfig 配置

Device Drivers > Character devices > sunxi g2d driver

5e1a49fe-ddea-11ed-bfe3-dac502259ad0.png

Device Tree 設(shè)備樹(shù)配置

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

注:status 要設(shè)定為“okay” 狀態(tài)。

重新編譯內(nèi)核

使用燒錄工具PhoenixSuit 將編譯打包好的img鏡像燒錄到開(kāi)發(fā)板。

adb shell 打開(kāi)控制終端查看設(shè)備節(jié)點(diǎn)G2D:

5e2532ce-ddea-11ed-bfe3-dac502259ad0.png

通過(guò)G2D設(shè)備節(jié)點(diǎn)進(jìn)行操作

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具體應(yīng)用

G2D sample目錄

5e406972-ddea-11ed-bfe3-dac502259ad0.png

進(jìn)行rotation,scale,格式轉(zhuǎn)換

具體實(shí)現(xiàn):將 nv21 格式的1920x1080圖轉(zhuǎn)換成rgb888 格式并放縮為640x360 大小。具體用到兩個(gè)功能,格式轉(zhuǎn)換和放縮。

首先根據(jù)1920x1080 nv21 格式以及 640x360 rgb888 格式申請(qǐng)?zhí)摂M地址空間以及轉(zhuǎn)換成物理地址(注意:g2d 轉(zhuǎn)換是在物理地址中完成的)

1920x1080 nv21 格式空間大?。ㄝ斎胛募?/strong>

Y 占 19201080 = 2073600 字節(jié)

UV 占 19201080 / 2 = 1036800 字節(jié)

5e45b3fa-ddea-11ed-bfe3-dac502259ad0.png

640x360 rgb888 格式空間大小(輸出文件):

RGB 占 6403603 = 691200 字節(jié)

另外:虛擬地址轉(zhuǎn)換成物理地址使用如下函數(shù):

g2d_getPhyAddrByVirAddr()

申請(qǐng)?zhí)摂M空間并轉(zhuǎn)換成物理空間完整函數(shù)如下:

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

通過(guò)fopen 傳菜間兩個(gè)文件句柄,fd_in fd_out 用來(lái)操作輸入輸出兩個(gè)文件資源。

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

打開(kāi)g2d 初始化,并開(kāi)始轉(zhuǎn)換

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;
 ? ?}
//具體轉(zhuǎn)化函數(shù):


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

轉(zhuǎn)化完成后將640x360 rgb888 圖資通過(guò)fd_out句柄存儲(chǔ)起來(lái)

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


轉(zhuǎn)化步驟總結(jié)

通過(guò)步驟3中的模塊化分析,可以看出g2d 轉(zhuǎn)化大概分為一下步驟:

為打開(kāi) iomen 初始化;

為src以及dst圖資申請(qǐng)?zhí)摂M地址空間并轉(zhuǎn)換成物理地址空間;

將src圖資放入虛擬地址空間,然后自動(dòng)映射到物理地址空間;

打開(kāi)g2d 設(shè)備節(jié)點(diǎn)進(jìn)行轉(zhuǎn)換(最重要的一環(huán),可以通過(guò)手冊(cè)分析具體怎么轉(zhuǎn)換的);

將轉(zhuǎn)換好的dst圖資保存起來(lái);






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • RGB
    RGB
    +關(guān)注

    關(guān)注

    4

    文章

    795

    瀏覽量

    58310
  • SRC
    SRC
    +關(guān)注

    關(guān)注

    0

    文章

    60

    瀏覽量

    17933
  • Shell
    +關(guān)注

    關(guān)注

    1

    文章

    361

    瀏覽量

    23237
  • V850
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    6740
  • ADB驅(qū)動(dòng)
    +關(guān)注

    關(guān)注

    0

    文章

    13

    瀏覽量

    6256

原文標(biāo)題:詳解全志V85x內(nèi)G2D模塊實(shí)現(xiàn)圖片格式步驟方法

文章出處:【微信號(hào):gh_79acfa3aa3e3,微信公眾號(hào):全志在線(xiàn)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【米爾-T113-i開(kāi)發(fā)板試用】G2D圖像處理硬件調(diào)用和測(cè)試

    /drivers/char/sunxi_g2d/g2d_bsp_v2.c 從g2d內(nèi)核驅(qū)動(dòng)中也可以得知,暫時(shí)沒(méi)有方法g2d設(shè)置自定義的YU
    發(fā)表于 02-17 18:26

    R128 SDK HAL 模塊開(kāi)發(fā)指南——G2D

    G2D G2D 驅(qū)動(dòng)主要實(shí)現(xiàn)圖像旋轉(zhuǎn)/數(shù)據(jù)格式/顏色空間轉(zhuǎn)換, 以及圖層合成功能(包括包括alpha、colorkey、rotate、mirror、rop、maskblt) 等圖形加速
    發(fā)表于 04-01 13:31

    圖片格式轉(zhuǎn)換BMP、GIF、Icon、Jpeg、Png、Wmf、Tiff......等

    構(gòu)造器節(jié)點(diǎn)調(diào)用Bitmap 進(jìn)行圖片格式轉(zhuǎn)換,具體實(shí)現(xiàn)如下:1.C#中代碼2.能轉(zhuǎn)換格式類(lèi)型:BMP、GIF、Icon、Jpeg、Png、Wmf、Tiff......等,3.Labvi
    發(fā)表于 02-28 10:40

    V853芯片 如何在Tina V85x平臺(tái)切換sensor?

    原文鏈接:https://bbs.aw-ol.com/topic/1666/作者@budbool目的V85x某方案目前默認(rèn)Sensor是GC2053。實(shí)際使用時(shí)若需要用到GC4663(比如wdr功能
    發(fā)表于 06-28 09:27

    每日推薦 | Tina V85x 平臺(tái)E907啟動(dòng)方式,OpenHarmony征文活動(dòng)獲獎(jiǎng)名單

    大家好,以下為電子發(fā)燒友推薦每日好帖,歡迎留言點(diǎn)評(píng)討論~1、V853芯片 在Tina下RISC-V核E907啟動(dòng)方式的選擇推薦理由:Tina V
    發(fā)表于 08-08 10:14

    V853芯片 Tina下RTSP環(huán)境搭建方法

    V85X RTSP環(huán)境搭建方法2.問(wèn)題背景本FAQ主要介紹Tina V85X上搭建RTSP環(huán)境的方法。目的對(duì)于小內(nèi)存的機(jī)器(不支持SD卡擴(kuò)
    發(fā)表于 08-08 10:50

    [開(kāi)源硬件大賽] 基于V853實(shí)現(xiàn)音頻播放器

    一、方案說(shuō)明1.設(shè)計(jì)方案思路和概況基于V85x 實(shí)現(xiàn)最小系統(tǒng)搭建,在此基礎(chǔ)上實(shí)現(xiàn)codec 音頻驅(qū)動(dòng),
    發(fā)表于 11-30 08:20

    V85X系列芯片PCB設(shè)計(jì)需要注意些什么?

    V85X (包括V853、V853S、V851S、V
    發(fā)表于 01-18 09:57

    V853芯片 如何在Tina V85x平臺(tái)切換sensor?

    V853開(kāi)發(fā)板購(gòu)買(mǎi)鏈接:https://item.hqchip.com/2500386536.html目的V85x某方案目前默認(rèn)Sensor是GC2053。實(shí)際使用時(shí)若需要用到GC
    發(fā)表于 02-13 11:03

    Android 10 - i.MX8MMini - g2d旋轉(zhuǎn)問(wèn)題求解

    禁用 g2d hwc(“啟用 Opengl ES 3D 合成!”),它會(huì)按預(yù)期工作,它看起來(lái)與截屏圖片完全一樣。
    發(fā)表于 02-28 06:40

    V85x MPP模塊概述以及編譯sample步驟

    /middleware/3.編譯一個(gè)MPP 模塊步驟(以 sample_g2d 為例)1)make menuconfig 配置配置項(xiàng),選中sample_g2d路徑:Allwinner
    發(fā)表于 04-17 09:41

    V851s、V853內(nèi)g2d模塊sample深究

    1. g2d 模塊概述g2d 主要功能:1)旋轉(zhuǎn):支持90、180、270旋轉(zhuǎn);2)鏡像反轉(zhuǎn):H / V;3)scale:放縮4)
    發(fā)表于 04-19 09:38

    C#教程之批量圖片格式轉(zhuǎn)換

    C#教程之批量圖片格式轉(zhuǎn)換,很好的C#資料,快來(lái)學(xué)習(xí)吧。
    發(fā)表于 04-20 11:13 ?8次下載

    小米官方科普什么是HEIF格式 與常見(jiàn)圖片格式有什么不同?

    小米10系列不但配備了1億像素后置四攝,還支持全新的HEIF圖片格式,可以在相機(jī)設(shè)置里選擇打開(kāi),還有溫馨提醒:“高效率圖片格式,可節(jié)省更多的存儲(chǔ)空間,但部分應(yīng)用可能不支持此格式。 ”
    的頭像 發(fā)表于 02-17 15:59 ?3.6w次閱讀

    如何快速完成圖片格式之間的相互轉(zhuǎn)換

    還是會(huì)需要用到一些特定的格式來(lái)完成工作,比如上傳個(gè)人信息身份的時(shí)候,那這個(gè)時(shí)候如果圖片格式不符合要求就需要將其格式進(jìn)行轉(zhuǎn)換,如何快速完成各種圖片格式之間的相互轉(zhuǎn)換并保證質(zhì)量,在本文中你
    的頭像 發(fā)表于 03-17 16:22 ?1792次閱讀