⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 osd_display.c

📁 基于GM8180的OSD源代码.从SDK包中挑出来的,是很不错的资料.
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/soundcard.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <sys/mman.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <sys/time.h> // struct itimeral. setitimer()
#include <pthread.h>

#include "mp4vosd.h"

#define FLCD_GET_DATA_SEP   0x46db
#define FLCD_GET_DATA       0x46dc
#define FLCD_SET_FB_NUM     0x46dd
#define FLCD_SWITCH_MODE    0x46de
#define FLCD_CLOSE_PANEL    0x46df

#define HZ 100 

struct flcd_data
{
    unsigned int buf_len;
    unsigned int uv_offset;
    unsigned int frame_no;
	unsigned int mp4_map_dma[10];
};

struct fb_buffer_t {
    unsigned char *data[3];
};

int fbfd=0;
int frame_number=0,fb_display=0;
volatile int ridx;
unsigned char *mmap_addr;
struct fb_var_screeninfo vinfo;
struct fb_buffer_t fb_buffer[10];   //give 10 frame buffer structure
struct flcd_data f_data;

    int width,height;
    int fbn=0; //init to 0
    FILE *fin=0;
    char filename[20];
    int res = 0;
    int g_fr;
    
    // osd related variables
    #define BACKGROUND_IMAGE_WIDTH  720
    #define BACKGROUND_IMAGE_HEIGHT 480
    #define FAVC_OSD_DEV  "/dev/fosd"
    char *sourcefile_name;
    FILE *sourcefile = NULL; // the source yuv file    
    unsigned int source_image_width,source_image_height; 
    unsigned int src_luma_y_size;
    unsigned int upper_left_x,upper_left_y;
    unsigned int alpha;    
    int             osd_mmap_addr;
    int             favc_osd_fd=0;
    FMP4_OSD_PARAM  mpeg4osd;

void init_osd(void) {
    int err;
    
    // to open the osd device
    if(favc_osd_fd==0)
      favc_osd_fd=open(FAVC_OSD_DEV,O_RDWR);

    if(favc_osd_fd == 0)
    {
	    printf("Fail to open %s\n",FAVC_OSD_DEV);
        exit (-1);
    }
    
    // to open the file for reading and writing
    if ((sourcefile = fopen (sourcefile_name, "rb")) == NULL)
    {
      printf ("Fatal: cannot open file '%s', exit (-1)\n",sourcefile_name);
      exit (-1);
    }
    
    src_luma_y_size   = (source_image_width * source_image_height)<<1;    
    // to get continuous memory from device driver by mmap
    osd_mmap_addr=(int)mmap(0,src_luma_y_size,
        PROT_READ|PROT_WRITE,MAP_SHARED,favc_osd_fd, 0);
    if(osd_mmap_addr<=0)
        exit (-1);
        
    mpeg4osd.output_width = BACKGROUND_IMAGE_WIDTH;
    mpeg4osd.output_height = BACKGROUND_IMAGE_HEIGHT;    
    //mpeg4osd.output_base_phy = (unsigned char*) lcd_mmap_addr;
    
    mpeg4osd.source_width = source_image_width;
    mpeg4osd.source_height = source_image_height;
    mpeg4osd.source_base_phy = (unsigned char*) (osd_mmap_addr);
    
    mpeg4osd.osd_x = upper_left_x;
    mpeg4osd.osd_y = upper_left_y;
    mpeg4osd.alpha = alpha;
    
    if((fread((void *)mpeg4osd.source_base_phy,sizeof(unsigned char),src_luma_y_size,sourcefile))!=src_luma_y_size) {      
      printf ("Fatal: cannot read %d bytes from file '%s'\n",src_luma_y_size,sourcefile_name);fflush(stdout);
      exit(-1);
    }
    
    err = ioctl(favc_osd_fd,FMPEG4_IOCTL_OSD_INIT,&mpeg4osd);
    if(err < 0)
    {
      close(favc_osd_fd);
	  printf("Error to set FMPEG4_IOCTL_OSD_INIT\n");
	  exit(-1);
    }
}


void close_osd(void) {
    
    munmap((void *)osd_mmap_addr,src_luma_y_size);
	fclose(sourcefile);    
    if(favc_osd_fd)
	  close(favc_osd_fd);
}

static void sig_show(void) {
    //if (ridx>9)
        //ridx =1;
    unsigned int stride_x;
    unsigned int stride_y;
    
    ridx%=frame_number;
        
    fb_display=ridx; 
    fflush(stdout);
    sprintf(filename,"display_cbycry_%d.yuv",fb_display);  
    fin=fopen(filename,"rb");
    if(!fin){
        printf("Fail to open %s\n",filename);
    }
    fread(fb_buffer[fb_display].data[0],width*height*2,1,fin);   //read Y
    //fread(fb_buffer[fb_display].data[1],width*height/4,1,fin); //read U
    //fread(fb_buffer[fb_display].data[2],width*height/4,1,fin); //read V    
    
    mpeg4osd.output_base_phy = (unsigned char*) fb_buffer[fb_display].data[0];
    stride_x = mpeg4osd.output_width - mpeg4osd.source_width;
    stride_y = mpeg4osd.output_height - mpeg4osd.source_height;
    stride_x = (stride_x>>2)<<2;
    // do some overlay move effect    
    if(stride_x) mpeg4osd.osd_x = (mpeg4osd.osd_x+8)%stride_x;
    if(stride_y) mpeg4osd.osd_y = (mpeg4osd.osd_y+8)%stride_y;
    ioctl(favc_osd_fd,FMPEG4_IOCTL_OSD_ALPHABLEND,&mpeg4osd);
    
    ioctl(fbfd,FLCD_SET_FB_NUM,&fb_display);
    ridx++;
    fclose(fin);
}

static void sig_int(void) {
    munmap(mmap_addr,f_data.frame_no*f_data.buf_len);
	printf("Ctrl+C to end program\n");
	fb_display=0;
    ioctl(fbfd,FLCD_SET_FB_NUM,&fb_display);
    
    close_osd();
    exit(0);
}

void showhint() {
    fprintf(stderr, "\nosd_display -s overlay_yuv -ws overlay_img_width -hs overlay_img_height -ulx upper_left_x -uly upper_left_y -alpha alpha_value -f framerate\n"    
    "## To add overlay image to background image (720x480) and display on TV.\n"
    "## Note that both images must be packed CbYCrY 422 format.\n"
    "## Options\n"
    "   -s :  specify the overlay image file name.\n"
    "   -ws :  set the overlay image width.\n"
    "   -hs :  set the overlay image height.\n"
    "   -ulx : set the upper-left x coordinate.\n"
    "          must be a multiple of 4 pixels for CbYCrY.\n"
    "   -uly : set the upper-left y coordinate.\n"
    "   -alpha : set the alpha value (0~255). 255 is totally opaque.\n"
    "   -f : specify the display framerate.\n"
    
    "## Example of usage:\n"
    "   osd_display -s welcome_256x64_cbycry.yuv -ws 256 -hs 64 -ulx 32 -uly 32 -alpha 128 -f 4\n"
    );
  exit(0);
}

void getparameter(int argc,char **argv) {
    int arg_index;

    for(arg_index=1;arg_index<argc;arg_index++) {
      if (0 == strncmp (argv[arg_index], "-s", 2)) {
        arg_index++;
        sourcefile_name=argv[arg_index];      
      } else if (0 == strncmp (argv[arg_index], "-ws", 3)) {
        arg_index++;
        sscanf(argv[arg_index],"%d",&source_image_width);
      } else if (0 == strncmp (argv[arg_index], "-hs", 3)) {
        arg_index++;
        sscanf(argv[arg_index],"%d",&source_image_height);      
      } else if (0 == strncmp (argv[arg_index], "-ulx", 4)) {
        arg_index++;
        sscanf(argv[arg_index],"%d",&upper_left_x);
      } else if (0 == strncmp (argv[arg_index], "-uly", 4)) {      
        arg_index++;
        sscanf(argv[arg_index],"%d",&upper_left_y);
      } else if (0 == strncmp (argv[arg_index], "-alpha", 6)) {      
        arg_index++;
        sscanf(argv[arg_index],"%d",&alpha);
      } else if (0 == strncmp (argv[arg_index], "-f", 2)) {      
        arg_index++;
        sscanf(argv[arg_index],"%d",&g_fr);
      } else {
        showhint(); 
      }
    }        
    
    printf("source yuv file name = %s\n",sourcefile_name);    
    printf("source image width = %d\n",source_image_width);
    printf("source image height = %d\n",source_image_height);
    printf("upper left x = %d\n",upper_left_x);
    printf("upper left y = %d\n",upper_left_y);  
    printf("alpha = %d\n",alpha);
    printf("framerate = %d\n",g_fr);
}

int main(int argc, char **argv)
{
    int i;
    struct itimerval tick;   
    long tmp; 
    
    if (argc != 15 ) {
        showhint();
        return 0;
    }
    getparameter(argc,argv);
    
    init_osd();
    
    ridx=1;
    
	fbfd = open("/dev/fb0", O_RDWR);
	if (!fbfd){
	    printf("LCD Error: cannot open framebuffer device.\n");
		exit(0);
	}

  	if (ioctl(fbfd,FLCD_SET_FB_NUM,&fbn)<0) {
   	    printf("Fail to set fb num\n");
   	    exit(0);
   	}
        
    // Get variable screen information
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)){
        printf("LCD Error: cannot reading variable information.\n");
		exit(0);
    }

	if (ioctl(fbfd,FLCD_GET_DATA_SEP, &f_data) < 0){
		printf("LCD Error: can not operate 0x%x\n", FLCD_GET_DATA_SEP);
		exit(0);
	}

    frame_number=f_data.frame_no;
    //printf("frame_number:%d; f_data.buf_len:%d\n",frame_number,f_data.buf_len);
	mmap_addr=(unsigned char *)mmap(0,f_data.frame_no*f_data.buf_len,PROT_READ|PROT_WRITE,MAP_SHARED,fbfd, 0);
	if(mmap_addr<0) {
	    printf("Fail to mmap flcd frame buffer");
	    exit(0);
	}   

	width = vinfo.xres;
    height = vinfo.yres;
	printf("LCD width:%d height:%d\n",width,height);
    printf("frame_number = %d\n",frame_number);
    
	for(i=0;i<frame_number;i++) {
        printf("Picture %d from address 0x%x\n",i,(unsigned char *)((unsigned int)mmap_addr+(i*f_data.buf_len)));
        fb_buffer[i].data[0]=(unsigned char *)((unsigned int)mmap_addr+(i*f_data.buf_len));
        //fb_buffer[i].data[1]=(unsigned char *)((unsigned int)mmap_addr+(i*f_data.buf_len))+f_data.uv_offset;
        //fb_buffer[i].data[2]=(unsigned char *)((unsigned int)mmap_addr+(i*f_data.buf_len))+f_data.uv_offset+(f_data.uv_offset/4);
	}

    if(signal(SIGINT,(void *)sig_int)==SIG_ERR)
       	printf("signal ctrl+c error\n");

    signal(SIGALRM, (void *)sig_show);  // Register sig_show to SIGALRM
       	
/* The First Picture (i=1) */
    ridx=1;
    sprintf(filename,"display_cbycry_%d.yuv",ridx);
    fin=fopen(filename,"rb");
    if(!fin) {
        printf("Fail to open %s\n",filename);
        return;
    }
    fread(fb_buffer[ridx].data[0],width*height*2,1,fin);   //read Y
    //fread(fb_buffer[ridx].data[1],width*height/4,1,fin); //read U
    //fread(fb_buffer[ridx].data[2],width*height/4,1,fin); //read V
    mpeg4osd.output_base_phy = (unsigned char*) fb_buffer[ridx].data[0];
    ioctl(favc_osd_fd,FMPEG4_IOCTL_OSD_ALPHABLEND,&mpeg4osd);
    
    fclose(fin);
    fbn=1;   
    ridx++; 
  	if (ioctl(fbfd,FLCD_SET_FB_NUM,&fbn)<0) {
   	    printf("Fail to set fb num\n");
   	    exit(0);
   	}

    // Initialize struct
    memset(&tick, 0, sizeof(tick));
    // Timeout to run function first time
    tick.it_value.tv_sec = 0;  // sec
    if (g_fr>0) {
	tmp = 1000000 * HZ / g_fr / 1000000;
	tmp = tmp * 1000000 / HZ - 1;
	tick.it_value.tv_usec = tmp;
	//printf("tmp:%ld\n",tmp);
    }
    else {
        tick.it_value.tv_usec = 0;
        printf("disable timer!\n");
    }      
    // Interval time to run function
    tick.it_interval = tick.it_value;
    // Set timer, ITIMER_REAL : real-time to decrease timer,
    //                          send SIGALRM when timeout
   	//Set timer
    res = setitimer(ITIMER_REAL, &tick, NULL);
    if (res) {
        printf("Set timer failed!!\n");
    }
    
// Start from the second Picture (i=2)
    
    printf("Please use [CTRL-C] to exit program!\n");
    fflush(stdout);
 
    while (1) {
        select(0, NULL, NULL, NULL, NULL);  	      
        //pause();
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -