📄 osd_display.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 + -