freescale i.MX6平臺如何實現圖像與視頻同屏顯示,或者兩者疊加。

一、準備工作

視頻採用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相關頭文件見資源鏈接:

https://download.csdn.net/download/u012478275/9502019

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