在Hi3531上運行QT, 並對 mpp/sample/hifb/sample_hifb.c 修改

想用hi3531做Qt的開發,網上有相關的資料,但是解釋就沒那麼清楚了,總結一下給大家分享.首先是網上已經有的文章.

http://blog.sina.com.cn/s/blog_48fba8050100y5yl.html

最近本人想要在Hi3531平臺上運行QT,故有一些心得,寫在這裏與大家分享一下:

1.首先運行sample中的sample_hifb,以便打開fb0;但是需要對代碼做一些修改:
將main函數中的 pthread_create(&phifb0,0,SAMPLE_HIFB_REFRESH,(void *)(&stInfo0));
改成 pthread_create(&phifb0,0,SAMPLE_HIFB_PTHREAD_RunHiFB,(void *)(&stInfo0));

將SAMPLE_HIFB_PTHREAD_RunHiFB函數中的HI_BOOL g_bCompress = HI_TRUE;
改成 HI_BOOL g_bCompress = HI_FALSE;


bShow = HI_TRUE;
if (ioctl(pstInfo->fd, FBIOPUT_SHOW_HIFB, &bShow) < 0)
{
printf(“FBIOPUT_SHOW_HIFB failed!\n”);
munmap(pShowScreen, fix.smem_len);
return HI_NULL;
}
後面加上
if (pstInfo->ctrlkey == 0)
{
while(1)
sleep(5);
}
到此修改完畢,然後編譯它。

2.接下來就可以試圖在Hi3531上運行QT了,
現在終端運行hifb的demo:sample_hifb
然後運行QT的demo:qt/demos/chip/chip -qws
至此你就可以看到QT的demo程序出現在屏幕上了。
enjoy!

但是這時候qt 程序只顯示在一個小方塊上,還有其他鼠標和圖片的干擾,分辨率也只有720P,而不是1080P.接下來我們做相應的修改,使其滿足我們開發Qt程序的需要.

一、設置顯存

在《HIFB開發指南》中講到要給每個圖形疊加層多大的顯存。

2.2 參數設置
HiFB可配置其管理的疊加圖形層物理顯存的大小。物理顯存大小決定了HiFB可使用
的最大物理顯存和系統的可設置虛擬分辨率。在加載HiFB驅動時通過參數傳遞設置物
理顯存大小,物理顯存的大小一經設置就不會改變。
參數video
video=“hifb:vram0_size:xxx, vram1_size:xxx,…”
z 選項之間用逗號“,”隔開。
z 選項和選項值之間用冒號“:”隔開。
z 如果某個圖層不配置物理顯存大小,則系統默認分配爲0。
z vram0_size ~ vram6_size分別對應於疊加圖形層0 ~ 疊加圖形層6。
其中,vramn_size:xxx表示對疊加圖形層n配置xxx K字節的物理顯存。
(1)對於FB標準模式,vramn_size和虛擬分辨率的關係如下:
Vramn_size * 1024 >= xres_virtual * yres_virtual * bpp;
其中:xres_virtual * yres_virtual是虛擬分辨率,bpp是每個像素所佔字節數。
(2)對於FB擴展模式,各個圖形層需要的內存大小取決於displaysize的大小、圖層像
素格式以及刷新模式,具體關係如下:

vramn_size * 1024 >= displaywidth * displayHeight * bpp * BufferMode;
如:圖形層0在1280720 分辨率、ARGB8888格式的2 buffer模式下需要的內存
vram0_size = 1280
72042 = 7200 K。
vramn_size必須是PAGE_SIZE(4K byte)的倍數,否則HiFB驅動強制將其設爲PAGE_SIZE的
倍數,向上取整。

參數默認值
如果加載HiFB驅動時不帶任何參數,則系統默認配置的參數值見下。
(1) Hi3531
video=“hifb:vram0_size:7200,vram1_size:7200,vram2_size:3240,vram3_size:3240,v
ram4_size:7200,vram5_size:128,vram6_size:128” softcursor=“off”

2.3 配置舉例
配置HiFB管理疊加圖形層的示例如下:
HiFB驅動的模塊文件爲hifb.ko。
z 配置HiFB管理一個疊加圖形層。
如果只需要HiFB管理疊加圖形層0,且最大虛擬分辨率爲720 x 576,用到的象素
格式爲ARGB1555,則疊加圖形層0需要的最小顯存爲720 x 576 x 2 = 829440 =
810K,配置參數如下:
insmod hifb.ko video=“hifb:vram0_size:810, vram2_size:0”。
如果採用的是double buffer的方式,則需要乘以2,即:
insmod hifb.ko video=“hifb:vram0_size:1620, vram2_size:0”。
z 配置HiFB管理多個疊加圖形層。
如果需要HiFB管理疊加圖形層0和疊加圖形層1兩個疊加層,且最大虛擬分辨率
爲720 x 576,用到的像素格式爲ARGB1555,則兩個疊加層需要的最小顯存都爲
720 x 576 x 2 = 829440 = 810K,配置參數如下:
insmod hifb.ko video=“hifb:vram0_size:810, vram1_size: 810”

我使用的是fb0設備,分辨率爲1080P=19201080, 19201080=2073600=2025k 這個應該是最小的內存數,我在 load3531中設置的參數爲

insmod hifb.ko video=“hifb:vram0_size:20000,vram1_size:7200,vram2_size:3240,vram3_size:3240,
vram4_size:7200,vram5_size:128,vram6_size:128” softcursor=“off” u32VcmpBufNum=2
apszLayerMmzNames=“mmzname0”,“mmzname1”,“graphics”,“mmzname0”

hifb:vram0_size:20000,20M肯定夠了。

二、打開HDMI接口,設置屏幕分辨率、屏幕起始座標,透明度等

下面修改 sample_hifb.c 文件.裏面有打開HDMI接口,設置屏幕分辨率、屏幕起始座標等

參考文檔: 《HiFB 開發指南》,《HiFB API參考》,《HiMPP 媒體處理軟件開發參考》

  1. main 函數

VO_PUB_ATTR_S
【說明】
定義視頻輸出公共屬性結構體。
【定義】
typedef struct hiVO_PUB_ATTR_S
{
HI_U32 u32BgColor; /* 設備背景色RGB表示*/
VO_INTF_TYPE_E enIntfType; /* Vo 接口類型*/
VO_INTF_SYNC_E enIntfSync; /* Vo接口時序類型*/
VO_SYNC_INFO_S stSyncInfo; /* Vo接口時序信息*/
HI_BOOL bDoubleFrame; /* 是否需要倍幀*/
} VO_PUB_ATTR_S;

u32BgColor 設備背景色,表示方法RGB888。

分辨率修改爲1080P,這個最後才找到。

stPubAttr.enIntfSync = VO_OUTPUT_1080P50;

只用一個線程phifb0設置屏幕分辨率和phifb1設置畫布起始點 就行了,所以可以把phifb2 的pthread_create, pthread_join 函數註釋掉。線程0的參數如下

/*start hifb */
stInfo0.layer = 0;
stInfo0.fd = -1;
stInfo0.ctrlkey = 0;

pthread_create(&phifb0,0,SAMPLE_HIFB_REFRESH,(void *)(&stInfo0));

  1. 函數HI_VOID *SAMPLE_HIFB_REFRESH(void *pData) 裏包含了設置屏幕分辨率的部分.先用FBIOGET_VSCREENINFO:獲取屏幕可變信息,再用 FBIOPUT_VSCREENINFO:設置屏幕可變信息 。

s32Ret = ioctl(pstInfo->fd, FBIOGET_VSCREENINFO, &stVarInfo);
if(s32Ret < 0)
{
printf(“GET_VSCREENINFO failed!\n”);
return HI_NULL;
}

if (ioctl(pstInfo->fd, FBIOPUT_SCREEN_ORIGIN_HIFB, &stPoint) < 0)
{
    printf("set screen original show position failed!\n");
    return HI_NULL;
}

//slq
maxW = 1920;
maxH = 1080;

stVarInfo.xres = stVarInfo.xres_virtual = maxW;
stVarInfo.yres = stVarInfo.yres_virtual = maxH;
s32Ret = ioctl(pstInfo->fd, FBIOPUT_VSCREENINFO, &stVarInfo);
if(s32Ret < 0)

{
printf(“PUT_VSCREENINFO failed!\n”);
return HI_NULL;
}
else
{
printf(“PUT_VSCREENINFO success!\n”);
}

緩存方式選擇,有無緩存,單緩存,雙緩存

switch (pstInfo->ctrlkey)

{
case 0 :
{
stLayerInfo.BufMode = HIFB_LAYER_BUF_ONE;
stLayerInfo.u32Mask = HIFB_LAYERMASK_BUFMODE;
break;
}

case 1 :
{
stLayerInfo.BufMode = HIFB_LAYER_BUF_DOUBLE;
stLayerInfo.u32Mask = HIFB_LAYERMASK_BUFMODE;
break;
}

default:
{
stLayerInfo.BufMode = HIFB_LAYER_BUF_NONE;
stLayerInfo.u32Mask = HIFB_LAYERMASK_BUFMODE;
}

}

這部分不知道幹啥的,應該是內存計算之類的吧,反正裏面的1280,720改成 1920,1080不會錯

for (y = 358; y < 362; y++)
{
for (x = 0; x < 1920; x++)
{
*(pBuf + y * maxW + x) = HIFB_RED_1555;
}
}
for (y = 0; y < 1080; y++)
{
for (x = 638; x < 642; x++)
{
*(pBuf + y * maxW + x) = HIFB_RED_1555;
}
}

我的主函數調用時,pstInfo->ctrlkey =0,所以只用修改 case 0 就可以了,虛擬寬度,高度和真實寬度,高度都設爲1920*1080

switch(pstInfo->ctrlkey)
{
case 0:
{
//slq
//window width and height

        var.xres_virtual = 1920; 
        var.yres_virtual = 1080;
        var.xres = 1920;
        var.yres = 1080;
    }
    break;
    
    case 1:
    {
        var.xres_virtual = 100;
        var.yres_virtual = 100;
        var.xres = 220;
        var.yres = 200;
    }
    break;
    
    case 2:
    {
        var.xres_virtual = SAMPLE_VIR_SCREEN_WIDTH;
        var.yres_virtual = SAMPLE_VIR_SCREEN_HEIGHT;
        var.xres = SAMPLE_IMAGE_WIDTH;
        var.yres = SAMPLE_IMAGE_HEIGHT;
    }
    break;
    case 3:
    {
        var.xres_virtual = 48;
        var.yres_virtual = 48;
        var.xres = 48;
        var.yres = 48;
    }
    break;
    default:
    {
        var.xres_virtual = 98;
        var.yres_virtual = 128;
        var.xres = 98;
        var.yres = 64;
    }
}
  1. 函數HI_VOID *SAMPLE_HIFB_PTHREAD_RunHiFB(void *pData)裏包含了設置屏幕起始座標等

/* 2. set the screen original position */
switch(pstInfo->ctrlkey)
{
case 0:
{
//slq
// window start pos
stPoint.s32XPos= 0;
stPoint.s32YPos = 0;
}
break;

    case 1:
    {
        stPoint.s32XPos = 150;
        stPoint.s32YPos = 350;
    }
    break;
    
    case 2:
    {
        stPoint.s32XPos = 384;
        stPoint.s32YPos = 100;
    }
    break;
    case 3:
    {
        stPoint.s32XPos = 450;
        stPoint.s32YPos = 150;
    }

break;
default:
{
stPoint.s32XPos = 0;
stPoint.s32YPos = 0;
}
}

設置 alpha 透明度, 修改 stAlpha.u8GlobalAlpha = 0xff; 即可.

/* 3.set alpha */
stAlpha.bAlphaEnable = HI_TRUE;
stAlpha.bAlphaChannel = HI_TRUE;
stAlpha.u8Alpha0 = 0xff;
stAlpha.u8Alpha1 = 0xff;

//slq
//set transparent 
stAlpha.u8GlobalAlpha = 0xff;




if (ioctl(pstInfo->fd, FBIOPUT_ALPHA_HIFB,  &stAlpha) < 0) 
{    
    printf("Set alpha failed!\n");
    close(pstInfo->fd);
    return HI_NULL;
}    
if(pstInfo->layer == HIFB_LAYER_CURSOR_0 || pstInfo->layer == HIFB_LAYER_CURSOR_1)
{     
  stColorKey.bKeyEnable = HI_TRUE;
  stColorKey.u32Key = 0x0; 
  if (ioctl(pstInfo->fd, FBIOPUT_COLORKEY_HIFB, &stColorKey) < 0) 
  {    
    printf("FBIOPUT_COLORKEY_HIFB!\n");
    close(pstInfo->fd);
    return HI_NULL;
  }    
}    

在上述工作完成後

退出編輯,make後在板子上運行,屏幕爲綠色,分辨率設置爲1920*1080

./sample_hifb

tw2865 0x50 set to PAL mode ok!
tw2865 0x54 set to PAL mode ok!
tw2865 0x52 set to PAL mode ok!
tw2865 0x56 set to PAL mode ok!
u32Width:1920, u32Square:2
HDMI start success.
PUT_VSCREENINFO success!
expected:two red line!

程序運行一會就會自動結束,爲了不讓其自動結束,在上述工作後添加如下代碼使程序一直運行,比如在設置好屏幕起始座標後

//slq
if (pstInfo->ctrlkey == 0)
{
while(1)
sleep(5);
}

在後臺運行 sample_hifb程序,便可再運行Qt 程序了

./sample_hifb &

tw2865 0x50 set to PAL mode ok!
tw2865 0x54 set to PAL mode ok!
tw2865 0x52 set to PAL mode ok!
tw2865 0x56 set to PAL mode ok!
u32Width:1920, u32Square:2
HDMI start success.
PUT_VSCREENINFO success!
expected:two red line!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章