Last active
May 7, 2019 00:09
-
-
Save steveway/9dc5897fcb6d4010d44e6a0aae0a8d96 to your computer and use it in GitHub Desktop.
This should add the ability to overlay images on a gmv video.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //==================================================== | |
| // gmplay 2.1 - geekmaster's kindle video player | |
| // Copyright (C) 2012 by geekmaster, with MIT license: | |
| // http://www.opensource.org/licenses/mit-license.php | |
| // Modified by Stefan Murawski ([email protected]) | |
| //---------------------------------------------------- | |
| // Tested on DX,DXG,K3,K4main,K4diags,K5main,K5diags. | |
| //---------------------------------------------------- | |
| #include <sys/ioctl.h> // ioctl | |
| #include <sys/mman.h> // mmap, munmap | |
| #include <stdio.h> // printf | |
| #include <stdlib.h> // malloc, free | |
| #include <linux/fb.h> // screeninfo | |
| #include <sys/time.h> // gettimeofday | |
| #include <unistd.h> // usleep | |
| #include <string.h> // memset, memcpy | |
| #include <fcntl.h> // open, close, write | |
| #include <time.h> // time | |
| typedef unsigned long u64; | |
| typedef unsigned int u32; | |
| typedef unsigned short u16; | |
| typedef unsigned char u8; | |
| u32 __invalid_size_argument_for_IOC; // ioctl.h bug fix for tcc | |
| //----- eink definitions from eink_fb.h and mxcfb.h ----- | |
| #define EU3 0x46dd | |
| #define EU50 0x4040462e | |
| #define EU51 0x4048462e | |
| struct update_area_t {int x1,y1,x2,y2,which_fx;u8 *buffer;}; | |
| struct mxcfb_rect {u32 top,left,width,height;}; | |
| struct mxcfb_alt_buffer_data {u32 phys_addr,width,height; | |
| struct mxcfb_rect alt_update_region;}; | |
| struct mxcfb_update_data {struct mxcfb_rect update_region; | |
| u32 waveform_mode,update_mode,update_marker;int temp;uint flags; | |
| struct mxcfb_alt_buffer_data alt_buffer_data;}; | |
| struct mxcfb_update_data51 {struct mxcfb_rect update_region; | |
| u32 waveform_mode,update_mode,update_marker; | |
| u32 hist_bw_waveform_mode,hist_gray_waveform_mode; | |
| int temp;uint flags;struct mxcfb_alt_buffer_data alt_buffer_data;}; | |
| //----- function prototypes ----- | |
| void gmplay4(void); | |
| void gmplay8(void); | |
| int getmsec(void); | |
| int gmlib(int); | |
| //----- gmlib global vars ----- | |
| enum GMLIB_op {GMLIB_INIT,GMLIB_CLOSE,GMLIB_UPDATE,GMLIB_VSYNC}; | |
| u8 *fb0=NULL; // framebuffer pointer | |
| int fdFB=0; // fb0 file descriptor | |
| int teu=0; // eink update time | |
| u32 fs=0; // fb0 stride | |
| u32 MX=0; // xres (visible) | |
| u32 MY=0; // yres (visible) | |
| u32 VY=0; // (VY>MY): mxcfb driver | |
| u8 ppb=0; // pixels per byte | |
| u32 fc=0; // frame counter | |
| time_t current_time; | |
| struct tm * time_info; | |
| char clockimagepath[99]; // space for "HH:MM\0" | |
| char clockmaskpath[99]; // space for "HH:MM\0" | |
| #define FBSIZE (600/8*800) | |
| #define MAGICTRANSPVALUE 0 | |
| //================================== | |
| // gmplay4 - play video on 4-bit fb0 | |
| //---------------------------------- | |
| void gmplay4(void) { | |
| u32 i,x,y,b,p,off=(MY/2-400)*fs+MX/4-150,fbsize=FBSIZE; u8 fbt[FBSIZE]; | |
| while (fread(fbt,fbsize,1,stdin)) { teu+=130; // teu: next update time | |
| if (getmsec()>teu+1000) continue; // drop frame if > 1 sec behind | |
| gmlib(GMLIB_VSYNC); // wait for fb0 ready | |
| for (y=0;y<800;y++) for (x=0;x<600;x+=8) { | |
| b=fbt[600/8*y+x/8]; i=y*fs+x/2+off; | |
| p=(b&1)*240; b>>=1; fb0[i]=p|(b&1)*15; b>>=1; | |
| p=(b&1)*240; b>>=1; fb0[i+1]=p|(b&1)*15; b>>=1; | |
| p=(b&1)*240; b>>=1; fb0[i+2]=p|(b&1)*15; b>>=1; | |
| p=(b&1)*240; b>>=1; fb0[i+3]=p|(b&1)*15; | |
| } fc++; gmlib(GMLIB_UPDATE); | |
| } | |
| } | |
| //================================== | |
| // gmplay4 - play video on 4-bit fb0 | |
| //---------------------------------- | |
| void gmplay4_addon(void) { | |
| u32 i,x,y,b,p,off=(MY/2-400)*fs+MX/4-150,fbsize=FBSIZE; | |
| u8 fbt[FBSIZE]; | |
| u32 addonimageb, addonmaskb, clockimageb, clockmaskb, addonimagep; | |
| u8 addonmaskp, clockimagep, clockmaskp; | |
| FILE *addonimagefp; | |
| FILE *addonmaskfp; | |
| u8 addonimage[FBSIZE]; | |
| u8 addonmask[FBSIZE]; | |
| FILE *clockimagefp; | |
| FILE *clockmaskfp; | |
| u8 clockimage[FBSIZE]; | |
| u8 clockmask[FBSIZE]; | |
| time(¤t_time); | |
| time_info = localtime(¤t_time); | |
| strftime(clockimagepath, sizeof(clockimagepath), "./clock_images/%H_%M.gmi", time_info); | |
| strftime(clockmaskpath, sizeof(clockmaskpath), "./clock_masks/%H_%M.gmi", time_info); | |
| addonimagefp = fopen("addonimage.gmi","rb"); | |
| while(addonimagefp == NULL){ | |
| addonimagefp = fopen("addonimage.gmi","rb"); | |
| } | |
| addonmaskfp = fopen("addonmask.gmi","rb"); | |
| while(addonmaskfp == NULL){ | |
| addonmaskfp = fopen("addonimage.gmi","rb"); | |
| } | |
| clockimagefp = fopen(clockimagepath,"rb"); | |
| while(clockimagefp == NULL){ | |
| clockimagefp = fopen(clockimagepath,"rb"); | |
| } | |
| clockmaskfp = fopen(clockmaskpath,"rb"); | |
| while(clockmaskfp == NULL){ | |
| clockmaskfp = fopen(clockmaskpath,"rb"); | |
| } | |
| while (fread(fbt,fbsize,1,stdin)) { | |
| teu+=130; // teu: next update time | |
| time(¤t_time); | |
| time_info = localtime(¤t_time); | |
| strftime(clockimagepath, sizeof(clockimagepath), "./clock_images/%H_%M.gmi", time_info); | |
| strftime(clockmaskpath, sizeof(clockmaskpath), "./clock_masks/%H_%M.gmi", time_info); | |
| if((time_info->tm_sec)==0){ | |
| fclose(addonimagefp); | |
| fclose(addonmaskfp); | |
| fclose(clockimagefp); | |
| fclose(clockmaskfp); | |
| clockimagefp = fopen(clockimagepath,"rb"); | |
| while(clockimagefp == NULL){ | |
| clockimagefp = fopen(clockimagepath,"rb"); | |
| } | |
| clockmaskfp = fopen(clockmaskpath,"rb"); | |
| while(clockmaskfp == NULL){ | |
| clockmaskfp = fopen(clockmaskpath,"rb"); | |
| } | |
| addonimagefp = fopen("addonimage.gmi","rb"); | |
| while(addonimagefp == NULL){ | |
| addonimagefp = fopen("addonimage.gmi","rb"); | |
| } | |
| addonmaskfp = fopen("addonmask.gmi","rb"); | |
| while(addonmaskfp == NULL){ | |
| addonmaskfp = fopen("addonimage.gmi","rb"); | |
| } | |
| } | |
| else{ | |
| rewind(addonimagefp); | |
| rewind(addonmaskfp); | |
| rewind(clockimagefp); | |
| rewind(clockmaskfp); | |
| } | |
| fread(clockimage,fbsize,1,clockimagefp); | |
| fread(clockmask,fbsize,1,clockmaskfp); | |
| //if(((time_info->tm_min %5) + time_info->tm_sec)==0){ | |
| //Every 5 Minutes | |
| //system("./update_twitimage.sh"); | |
| //} | |
| fread(addonimage,fbsize,1,addonimagefp); | |
| fread(addonmask,fbsize,1,addonmaskfp); | |
| if (getmsec()>teu+1000) continue; // drop frame if > 1 sec behind | |
| gmlib(GMLIB_VSYNC); // wait for fb0 ready | |
| for (y=0;y<800;y++) for (x=0;x<600;x+=8) { | |
| addonimageb = addonimage[600/8*y+x/8]; | |
| addonmaskb = addonmask[600/8*y+x/8]; | |
| clockimageb = clockimage[600/8*y+x/8]; | |
| clockmaskb = clockmask[600/8*y+x/8]; | |
| b=fbt[600/8*y+x/8]; i=y*fs+x/2+off; | |
| addonmaskp=(addonmaskb&1)*240; addonmaskb>>=1; | |
| addonimagep=(addonimageb&1)*240; addonimageb>>=1; | |
| clockmaskp=(clockmaskb&1)*240; clockmaskb>>=1; | |
| clockimagep=(clockimageb&1)*240; clockimageb>>=1; | |
| p=(b&1)*240; b>>=1; | |
| if((addonmaskp|(addonmaskb&1)*15) != MAGICTRANSPVALUE){ | |
| fb0[i]=(addonimagep|(addonimageb&1)*15); | |
| } | |
| //if(1==0){ | |
| else if((clockmaskp|(clockmaskb&1)*15) != MAGICTRANSPVALUE){ | |
| fb0[i]=(clockimagep|(clockimageb&1)*15)|0xFF; | |
| } | |
| else{ fb0[i]=p|(b&1)*15; } | |
| addonmaskb>>=1; addonimageb>>=1; b>>=1; | |
| addonmaskp=(addonmaskb&1)*240; addonmaskb>>=1; | |
| addonimagep=(addonimageb&1)*240; addonimageb>>=1; | |
| clockmaskp=(clockmaskb&1)*240; clockmaskb>>=1; | |
| clockimagep=(clockimageb&1)*240; clockimageb>>=1; | |
| p=(b&1)*240; b>>=1; | |
| if((addonmaskp|(addonmaskb&1)*15) != MAGICTRANSPVALUE){ | |
| fb0[i +1]=(addonimagep|(addonimageb&1)*15); | |
| } | |
| //if(1==0){ | |
| else if((clockmaskp|(clockmaskb&1)*15) != MAGICTRANSPVALUE){ | |
| fb0[i+ 1]=(clockimagep|(clockimageb&1)*15)|0xFF; | |
| } | |
| else{ fb0[i +1]=p|(b&1)*15; } | |
| addonmaskb>>=1; addonimageb>>=1; b>>=1; | |
| addonmaskp=(addonmaskb&1)*240; addonmaskb>>=1; | |
| addonimagep=(addonimageb&1)*240; addonimageb>>=1; | |
| clockmaskp=(clockmaskb&1)*240; clockmaskb>>=1; | |
| clockimagep=(clockimageb&1)*240; clockimageb>>=1; | |
| p=(b&1)*240; b>>=1; | |
| if((addonmaskp|(addonmaskb&1)*15) != MAGICTRANSPVALUE){ | |
| fb0[i + 2]=(addonimagep|(addonimageb&1)*15); | |
| } | |
| //if(1==0){ | |
| else if((clockmaskp|(clockmaskb&1)*15) != MAGICTRANSPVALUE){ | |
| fb0[i + 2]=(clockimagep|(clockimageb&1)*15)|0xFF; | |
| } | |
| else{ fb0[i + 2]=p|(b&1)*15; } | |
| addonmaskb>>=1; addonimageb>>=1; b>>=1; | |
| addonmaskp=(addonmaskb&1)*240; addonmaskb>>=1; | |
| addonimagep=(addonimageb&1)*240; addonimageb>>=1; | |
| clockmaskp=(clockmaskb&1)*240; clockmaskb>>=1; | |
| clockimagep=(clockimageb&1)*240; clockimageb>>=1; | |
| p=(b&1)*240; b>>=1; | |
| if((addonmaskp|(addonmaskb&1)*15) != MAGICTRANSPVALUE){ | |
| fb0[i + 3]=(addonimagep|(addonimageb&1)*15); | |
| } | |
| //if(1==0){ | |
| else if((clockmaskp|(clockmaskb&1)*15) != MAGICTRANSPVALUE){ | |
| fb0[i + 3]=(clockimagep|(clockimageb&1)*15)|0xFF; | |
| } | |
| else{ fb0[i + 3]=p|(b&1)*15; } | |
| //p=(b&1)*240; b>>=1; fb0[i]=p|(b&1)*15; b>>=1; | |
| //p=(b&1)*240; b>>=1; fb0[i+1]=p|(b&1)*15; b>>=1; | |
| //p=(b&1)*240; b>>=1; fb0[i+2]=p|(b&1)*15; b>>=1; | |
| //p=(b&1)*240; b>>=1; fb0[i+3]=p|(b&1)*15; | |
| } fc++; gmlib(GMLIB_UPDATE); | |
| } | |
| } | |
| //================================== | |
| // gmplay8 - play video on 8-bit fb0 | |
| //---------------------------------- | |
| void gmplay8(void) { | |
| u32 i,x,y,b,fbsize=FBSIZE; | |
| u32 addonimageb, addonmaskb, clockimageb, clockmaskb; | |
| u8 fbt[FBSIZE]; | |
| FILE *addonimagefp; | |
| FILE *addonmaskfp; | |
| u8 addonimage[FBSIZE]; | |
| u8 addonmask[FBSIZE]; | |
| FILE *clockimagefp; | |
| FILE *clockmaskfp; | |
| u8 clockimage[FBSIZE]; | |
| u8 clockmask[FBSIZE]; | |
| while (fread(fbt,fbsize,1,stdin)) { | |
| time(¤t_time); | |
| time_info = localtime(¤t_time); | |
| strftime(clockimagepath, sizeof(clockimagepath), "./clock_images/%H_%M.gmi", time_info); | |
| strftime(clockmaskpath, sizeof(clockmaskpath), "./clock_masks/%H_%M.gmi", time_info); | |
| printf(clockimagepath); | |
| clockimagefp = fopen(clockimagepath,"rb"); | |
| clockmaskfp = fopen(clockmaskpath,"rb"); | |
| fread(clockimage,fbsize,1,clockimagefp); | |
| fread(clockmask,fbsize,1,clockmaskfp); | |
| if(((time_info->tm_min %5) + time_info->tm_sec)==0){ | |
| //Every 5 Minutes | |
| system("./update_twitimage.sh"); | |
| } | |
| addonimagefp = fopen("addonimage.gmi","rb"); | |
| addonmaskfp = fopen("addonmask.gmi","rb"); | |
| fread(addonimage,fbsize,1,addonimagefp); | |
| fread(addonmask,fbsize,1,addonmaskfp); | |
| teu+=130; // teu: next update time | |
| if (getmsec()>teu+1000) continue; // drop frame if > 1 sec behind | |
| gmlib(GMLIB_VSYNC); // wait for fb0 ready | |
| for (y=0;y<800;y++) for (x=0;x<600;x+=8) { | |
| b=fbt[600/8*y+x/8]; | |
| addonimageb=addonimage[600/8*y+x/8]; | |
| addonmaskb=addonmask[600/8*y+x/8]; | |
| clockimageb=clockimage[600/8*y+x/8]; | |
| clockmaskb=clockmask[600/8*y+x/8]; | |
| i=y*fs+x; | |
| if(addonmaskb != MAGICTRANSPVALUE){ fb0[i]=(addonimageb&1)*255; } | |
| else if(clockmaskb != MAGICTRANSPVALUE){ fb0[i]=(clockimageb&1)*255;} | |
| else{ fb0[i]=(b&1)*255; } | |
| b>>=1; addonimageb>>=1; addonmaskb>>=1; clockimageb>>=1; clockmaskb>>=1; | |
| if(addonmaskb != MAGICTRANSPVALUE){ fb0[i+1]=(addonimageb&1)*255; } | |
| else if(clockmaskb != MAGICTRANSPVALUE){ fb0[i+1]=(clockimageb&1)*255;} | |
| else{ fb0[i+1]=(b&1)*255; } | |
| b>>=1; addonimageb>>=1; addonmaskb>>=1; clockimageb>>=1; clockmaskb>>=1; | |
| if(addonmaskb != MAGICTRANSPVALUE){ fb0[i+2]=(addonimageb&1)*255; } | |
| else if(clockmaskb != MAGICTRANSPVALUE){ fb0[i+2]=(clockimageb&1)*255;} | |
| else{ fb0[i+2]=(b&1)*255; } | |
| b>>=1; addonimageb>>=1; addonmaskb>>=1; clockimageb>>=1; clockmaskb>>=1; | |
| if(addonmaskb != MAGICTRANSPVALUE){ fb0[i+3]=(addonimageb&1)*255; } | |
| else if(clockmaskb != MAGICTRANSPVALUE){ fb0[i+3]=(clockimageb&1)*255;} | |
| else{ fb0[i+3]=(b&1)*255; } | |
| b>>=1; addonimageb>>=1; addonmaskb>>=1; clockimageb>>=1; clockmaskb>>=1; | |
| if(addonmaskb != MAGICTRANSPVALUE){ fb0[i+4]=(addonimageb&1)*255; } | |
| else if(clockmaskb != MAGICTRANSPVALUE){ fb0[i+4]=(clockimageb&1)*255;} | |
| else{ fb0[i+4]=(b&1)*255; } | |
| b>>=1; addonimageb>>=1; addonmaskb>>=1; clockimageb>>=1; clockmaskb>>=1; | |
| if(addonmaskb != MAGICTRANSPVALUE){ fb0[i+5]=(addonimageb&1)*255; } | |
| else if(clockmaskb != MAGICTRANSPVALUE){ fb0[i+5]=(clockimageb&1)*255;} | |
| else{ fb0[i+5]=(b&1)*255; } | |
| b>>=1; addonimageb>>=1; addonmaskb>>=1; clockimageb>>=1; clockmaskb>>=1; | |
| if(addonmaskb != MAGICTRANSPVALUE){ fb0[i+6]=(addonimageb&1)*255; } | |
| else if(clockmaskb != MAGICTRANSPVALUE){ fb0[i+6]=(clockimageb&1)*255;} | |
| else{ fb0[i+6]=(b&1)*255; } | |
| b>>=1; addonimageb>>=1; addonmaskb>>=1; clockimageb>>=1; clockmaskb>>=1; | |
| if(addonmaskb != MAGICTRANSPVALUE){ fb0[i+7]=(addonimageb&1)*255; } | |
| else if(clockmaskb != MAGICTRANSPVALUE){ fb0[i+7]=(clockimageb&1)*255;} | |
| else{ fb0[i+7]=(b&1)*255; } | |
| /* | |
| fb0[i+1]=(b&1)*255; b>>=1; | |
| fb0[i+2]=(b&1)*255; b>>=1; | |
| fb0[i+3]=(b&1)*255; b>>=1; | |
| fb0[i+4]=(b&1)*255; b>>=1; | |
| fb0[i+5]=(b&1)*255; b>>=1; | |
| fb0[i+6]=(b&1)*255; b>>=1; | |
| fb0[i+7]=(b&1)*255; | |
| */ | |
| } fc++; gmlib(GMLIB_UPDATE); | |
| fclose(addonimagefp); | |
| fclose(addonmaskfp); | |
| } | |
| } | |
| //==================================== | |
| // gmlib - geekmaster function library | |
| // op (init, update, vsync, close) | |
| //------------------------------------ | |
| int gmlib(int op) { | |
| static struct update_area_t ua={0,0,600,800,21,NULL}; | |
| static struct mxcfb_update_data ur={ | |
| {0,0,600,800},257,0,1,0x1001,0,{0,0,0,{0,0,0,0}}}; | |
| static struct mxcfb_update_data51 ur51={ | |
| {0,0,600,800},257,0,1,0,0,0x1001,0,{0,0,0,{0,0,0,0}}}; | |
| static int eupcode; static void *eupdata=NULL; | |
| struct fb_var_screeninfo screeninfo; | |
| if (GMLIB_INIT==op) { | |
| teu=getmsec(); | |
| fdFB=open("/dev/fb0",O_RDWR); | |
| ioctl(fdFB,FBIOGET_VSCREENINFO,&screeninfo); | |
| ppb=8/screeninfo.bits_per_pixel; | |
| fs=screeninfo.xres_virtual/ppb; | |
| VY=screeninfo.yres_virtual; | |
| MX=screeninfo.xres; | |
| MY=screeninfo.yres; | |
| ua.x2=MX; | |
| ua.y2=MY; | |
| ur.update_region.width=MX; | |
| ur.update_region.height=MY; | |
| fb0=(u8 *)mmap(0,MY*fs,PROT_READ|PROT_WRITE,MAP_SHARED,fdFB,0); // map fb0 | |
| if (VY>MY) { | |
| eupcode=EU50; | |
| eupdata=&ur; | |
| ur.update_mode=0; | |
| if (ioctl(fdFB,eupcode,eupdata)<0) { | |
| eupcode=EU51; | |
| eupdata=&ur51; | |
| } | |
| } else { eupcode=EU3; eupdata=&ua; } | |
| //system("eips -f -c;eips -c"); | |
| //sleep(1); | |
| } else if (GMLIB_UPDATE==op) { | |
| if (ioctl(fdFB,eupcode,eupdata)<0) {}//system("eips ''");} // 5.1.0 fallback | |
| } else if (GMLIB_VSYNC==op) { while (teu>getmsec()) usleep(1000); // fb0 busy | |
| } else if (GMLIB_CLOSE==op) { gmlib(GMLIB_UPDATE); //sleep(1); // last screen | |
| //system("eips -f -c;eips -c"); | |
| munmap(fb0,MY*fs); | |
| close(fdFB); | |
| } else { return -1; } | |
| return 0; | |
| } | |
| //==================================== | |
| // getmsec - get msec since first call | |
| // (tick counter wraps every 12 days) | |
| //------------------------------------ | |
| int getmsec(void) { | |
| int tc; static int ts=0; struct timeval tv; | |
| gettimeofday(&tv,NULL); tc=tv.tv_usec/1000+1000*(0xFFFFF&tv.tv_sec); | |
| if (0==ts) ts=tc; | |
| return tc-ts; | |
| } | |
| //================== | |
| // main - start here | |
| //------------------ | |
| int main(void) { | |
| int i; | |
| gmlib(GMLIB_INIT); | |
| if (ppb-1) { gmplay4_addon(); } else { gmplay8(); } | |
| i=getmsec()/100; | |
| // printf("%d frames in %0.1f secs = %2.1f FPS\n", fc,(double)i/10.0,(double)fc*10.0/i); | |
| gmlib(GMLIB_CLOSE); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment