一、準備工作
視頻採用gstreamer方案,圖像採用qt方案。u-boot下配置displayinfo環境變量:
setenv displayinfo video=mxcfb0:dev=hdmi,720x576M@60,if=RGB24
sa
reset
這裏可以看到,我們是從hdmi輸出,採用D1分辨率。
二、實現原理
在i.MX6下,/dev下面有兩個fb設備,分別是/dev/fb0和/dev/fb1,默認fb1是fb0的overlay層。
我們通過控制fb1的透明度就可以實現同屏顯示,或着疊加。
事實上,gstreamer的視頻方案,默認是顯示在fb1,而qt程序,我們則可以使其運行在fb0上。
(注意,這是重點,雖然你運行gstreamer程序,打印會友好的顯示“display(/dev/fb0) resolution is (720x576).”,但實際上是運行在fb1的)
三、運用場景
準備一個fb1設置程序fb_setup,
運行gstreamer,qt。後根據需要調用fb_setup進行設置。
四、fb_setup實現
效果一,設置fb1全透明,暴露fb0底圖,實現圖片全屏顯示。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <unistd.h>
#include <linux/mxcfb.h>
#include <sys/ioctl.h>
int main(int argc, char** argv)
{
int fd = 0;
int retval;
struct mxcfb_gbl_alpha gbl_alpha;
if ((fd = open("/dev/fb1", O_RDWR, 0)) < 0)
{
printf("open /dev/fb1 fail\n");
goto err0;
}
gbl_alpha.enable = 1;
gbl_alpha.alpha = 0x00;
retval = ioctl(fd, MXCFB_SET_GBL_ALPHA, &gbl_alpha);
if (retval < 0)
{
printf("fb ioctl MXCFB_SET_GBL_ALPHA fail\n");
goto err1;
}
printf("global alpha enabled,set alpha=0x00\n");
err1:
close(fd);
err0:
return retval;
}
效果二,視頻全屏
上述代碼將gbl_alpha.alpha=0x00改爲0xff。
效果三,視頻圖片同屏顯示
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <unistd.h>
#include <linux/mxcfb.h>
#include <sys/ioctl.h>
int main(int argc, char** argv)
{
int fd = 0;
int retval = 0;
struct fb_var_screeninfo fb_var;
struct mxcfb_loc_alpha loc_alpha;
int screen_width = 0;
int screen_size = 0;
int alp_size = 0;
void* fbbuf = NULL;
void* alpbuf = NULL;
int i, j;
if ((fd = open("/dev/fb1", O_RDWR, 0)) < 0)
{
printf("open /dev/fb1 fail\n");
retval = -1;
goto err0;
}
loc_alpha.enable = 1;
loc_alpha.alpha_in_pixel = 0;
retval = ioctl(fd, MXCFB_SET_LOC_ALPHA, &loc_alpha);
if (retval < 0)
{
printf("fb ioctl MXCFB_SET_LOC_ALPHA fail\n");
goto err1;
}
retval = ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
if (retval < 0)
{
printf("fb ioctl FBIOGET_VSCREENINFO fail\n");
goto err1;
}
alp_size = fb_var.xres * fb_var.yres;
alpbuf = mmap(0, alp_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, loc_alpha.alpha_phy_addr0);
memset(alpbuf, 0x00, alp_size/4);
memset(alpbuf+alp_size/4, 0xFF, alp_size/4);
memset(alpbuf+alp_size/2, 0xFF, alp_size/4);
memset(alpbuf+alp_size*3/4, 0xFF, alp_size/4);
munmap(alpbuf, alp_size);
alp_size = fb_var.xres * fb_var.yres;
alpbuf = mmap(0, alp_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, loc_alpha.alpha_phy_addr1);
memset(alpbuf, 0x00, alp_size/4);
memset(alpbuf+alp_size/4, 0xFF, alp_size/4);
memset(alpbuf+alp_size/2, 0xFF, alp_size/4);
memset(alpbuf+alp_size*3/4, 0xFF, alp_size/4);
munmap(alpbuf, alp_size);
ioctl(fd, MXCFB_WAIT_FOR_VSYNC, 0);
retval = ioctl(fd, FBIOBLANK, FB_BLANK_UNBLANK);
if (retval < 0)
{
printf("fb ioctl FBIOBLANK fail\n");
goto err1;
}
err1:
close(fd);
err0:
return retval;
}
比如上述代碼實現了前1/4行顯示圖片,後3/4行顯示視頻。
備註:alpha_phy_addr0和alpha_phy_addr1要同步設置,不然視頻會閃爍。
mxcfb.h相關頭文件見資源鏈接: