image28

VFX - Live SDL Partial Background Subtraction

Jul 29th, 2016
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.30 KB | None | 0 0
  1. // TCap v0.1
  2. // (C) Thomas Hargrove
  3. // http://toonarchive.com/tcap
  4.  
  5. /***************************************************************************
  6.  *                                                                         *
  7.  *   This program is free software; you can redistribute it and/or modify  *
  8.  *   it under the terms of the GNU General Public License as published by  *
  9.  *   the Free Software Foundation; either version 2 of the License, or     *
  10.  *   (at your option) any later version.                                   *
  11.  *                                                                         *
  12.  ***************************************************************************/
  13.  
  14. // SDL and bluescreen by Kevin
  15.  
  16. #include <unistd.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <fcntl.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/mman.h>
  22. #include <errno.h>
  23. #include <libv4l1-videodev.h>
  24. #include "record.h"
  25. #include <SDL.h>
  26. #include <png.h>
  27. #include <SDL/SDL_image.h>
  28.  
  29. static struct   video_capability  capability;
  30. static int  fd = -1;
  31. static struct   video_mbuf gb_buffers = { 2*WIDTH*HEIGHT*3, 0, {0,WIDTH*HEIGHT*3 }};
  32. static char     *map = NULL;
  33. static struct   video_mmap my_buf;
  34.  
  35. struct video_channel vch;
  36.  
  37.  
  38. //#define   WIDTH 960
  39. //#define   HEIGHT 720
  40. #define     p(x) printf("%s",x);
  41. static char     *map;
  42. #define OUTFILE "screenshot-"
  43.  
  44. SDL_Surface *screen;
  45. SDL_Surface *offscreen;
  46. SDL_Event event;
  47.  
  48. /* Copies map to screen, then updates the screen */
  49. void copytoscreen(char* tmap, int startRecord, int count) {
  50.     offscreen = SDL_CreateRGBSurfaceFrom((void *) tmap, WIDTH, HEIGHT, 24, WIDTH*3, 0x0000FF, 0x00FF00, 0xFF0000, 0x000000);
  51.  
  52.     if ( startRecord )
  53.     {
  54.  
  55.    char temp[10];
  56.          char outfileCur[32768];
  57.         sprintf(temp, "%d", count);
  58.         strcpy(outfileCur,OUTFILE);
  59.         strcat(outfileCur,temp);
  60.         strcat(outfileCur,".png");
  61.         if( png_save_surface(outfileCur, offscreen) < 0 ) exit(-1);
  62.     }
  63.  
  64.     SDL_BlitSurface(offscreen, NULL, screen, NULL);
  65.     SDL_UpdateRect(screen, 0, 0, 0, 0);
  66.     SDL_FreeSurface(offscreen);
  67. }
  68.  
  69.  
  70. int main(int argc, char *argv[])
  71. {
  72.     char my_video_dev[100]  = "/dev/video0";
  73.  
  74.    // --------------------------------------------------------------------------
  75.    // Get the v4l capture set up
  76.    // --------------------------------------------------------------------------
  77.    if (-1 == (fd = open(my_video_dev, O_RDWR))) {
  78.     printf("Error opening device: %s\n", my_video_dev);
  79.      return(-1);
  80.    }
  81.    if (-1 == ioctl(fd,VIDIOCGCAP,&capability)) {
  82.     printf("Error: ioctl(fd,VIDIOCGCAP,&capability)\n");
  83.      return(-2);
  84.    }
  85.  
  86.    vch.channel = 0;
  87.    vch.norm = VIDEO_MODE_PAL;
  88.    if(-1 == ioctl(fd, VIDIOCSCHAN,&vch)) {
  89.          perror("Setting channel\n");
  90.          return(-3);
  91.    }
  92.  
  93.  
  94.    fcntl(fd,F_SETFD,FD_CLOEXEC);
  95.    if (-1 == ioctl(fd,VIDIOCGMBUF,&gb_buffers)) {
  96.     printf("Error: Error getting buffers\n");
  97.      return(-4);
  98.    }
  99.  
  100.    map = mmap(0,gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
  101.    if (map == NULL) {
  102.     printf("Error: Mmap returned NULL\n");
  103.      return(-5);
  104.    }
  105.    // Set up out capture to use the correct resolution
  106.    my_buf.width = WIDTH;
  107.    my_buf.height = HEIGHT;
  108.    my_buf.format = VIDEO_PALETTE_RGB24;
  109.  
  110.    // Tell the capture card to fill frame 0
  111.    my_buf.frame = 0;
  112.    if (-1 == ioctl(fd, VIDIOCMCAPTURE, &my_buf)) {
  113.     printf("Error: Grabber chip can't sync (no station tuned in?)\n");
  114.      return(-6);
  115.    }
  116.  
  117.    int done = 0;
  118.  
  119.    // --------------------------------------------------------------------------
  120.    // Set up out video output
  121.    // --------------------------------------------------------------------------
  122.  
  123.    SDL_Init(SDL_INIT_VIDEO);
  124.    screen = SDL_SetVideoMode(WIDTH, HEIGHT, 16, SDL_SWSURFACE);
  125.    if ( screen == NULL ) {
  126.     printf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
  127.     SDL_GetError());
  128.     exit(1);
  129.    }
  130.    SDL_WM_SetCaption("", NULL);
  131.  
  132. char *background;
  133. int subtract=0;
  134. int capBackground=0;
  135. int haveBackground=0;
  136. int startRecord=0;
  137. int x,y,z,d;
  138.    int frame=0;
  139.  
  140. background=malloc((WIDTH*HEIGHT*3)*FRAMES);
  141.  
  142.    while ( ! done ) {
  143.     while (SDL_PollEvent(&event))
  144.     {
  145.        switch(event.type)
  146.        {
  147.                   case SDL_KEYDOWN:
  148.                 switch( event.key.keysym.sym ){
  149.           case SDLK_ESCAPE: done =1; break;
  150.           case SDLK_b: capBackground=1; break;
  151.           case SDLK_s:
  152.           subtract=!subtract;
  153.           break;
  154.           case SDLK_r:
  155.           startRecord=!startRecord;
  156.           break;
  157.                     default:
  158.                         break;
  159.                 }
  160.                 break;
  161.           case SDL_QUIT: done = 1; break;
  162.        }
  163.     }
  164.  
  165.     my_buf.frame = 1;
  166.     if (-1 == ioctl(fd, VIDIOCMCAPTURE, &my_buf)) {
  167.         printf("Error: Grabber chip can't sync (no station tuned in?)\n");
  168.         done=1;
  169.     }
  170.  
  171.     copytoscreen(map,0,0);
  172.     my_buf.frame = 0;
  173.     if (-1 == ioctl(fd, VIDIOCSYNC, &my_buf.frame)) {
  174.          printf("Error on sync!\n");
  175.          done=1;
  176.     }
  177.  
  178.     if ( capBackground )
  179.     {
  180.         printf("Capturing background\n");
  181.         while ( capBackground < FRAMES+1 )
  182.         {
  183.             my_buf.frame = 1;
  184.     if (-1 == ioctl(fd, VIDIOCMCAPTURE, &my_buf)) {
  185.         printf("Error: Grabber chip can't sync (no station tuned in?)\n");
  186.         done=1;
  187.     }
  188.  
  189.  
  190.     my_buf.frame = 0;
  191.     if (-1 == ioctl(fd, VIDIOCSYNC, &my_buf.frame)) {
  192.          printf("Error on sync!\n");
  193.          done=1;
  194.         }
  195.  
  196.         memcpy(background+((capBackground-1)*WIDTH*HEIGHT*3),map,WIDTH*HEIGHT*3);
  197.  
  198.         capBackground++;
  199.     }
  200.     haveBackground=1;
  201.  
  202.         capBackground=0;
  203.     }
  204.  
  205.     if ( ( subtract ) && ( haveBackground ) )
  206.     {
  207.         //printf("Subtracting background\n");
  208.                 for(x=0; x<WIDTH*HEIGHT*3*FRAMES; x=x+3)
  209.         {
  210.                     if (( (int)background[x] > (int)map[x%(WIDTH*HEIGHT*3)]-VARIATION/2 ) && ( (int)background[x] < (int)map[x%(WIDTH*HEIGHT*3)]+VARIATION/2 ))
  211.             {
  212.                 if (( (int)background[x+1] > (int)map[(x+1)%(WIDTH*HEIGHT*3)]-VARIATION/2 ) && ( (int)background[x+1] < (int)map[(x+1)%(WIDTH*HEIGHT*3)]+VARIATION/2 ))
  213.                 {
  214.                     if (( (int)background[x+2] > (int)map[(x+2)%(WIDTH*HEIGHT*3)]-VARIATION/2 ) && ( (int)background[x+2] < (int)map[(x+2)%(WIDTH*HEIGHT*3)]+VARIATION/2 ))
  215.                     {
  216.                         map[(x)%(WIDTH*HEIGHT*3)] = (char)0;
  217.                         map[(x+1)%(WIDTH*HEIGHT*3)] = (char)0;
  218.                         map[(x+2)%(WIDTH*HEIGHT*3)] = (char)255;
  219.                         }
  220.                     }
  221.                 }
  222.             }
  223.     }
  224.  
  225.     if (startRecord )
  226.     {
  227.         frame++;
  228.     }
  229.  
  230.     copytoscreen(map,startRecord,frame);
  231.  
  232.    }
  233.  
  234.    SDL_Quit();
  235.  
  236.    return EXIT_SUCCESS;
  237. }
  238.  
  239.  
  240. static int png_colortype_from_surface(SDL_Surface *surface)
  241. {
  242.     int colortype = PNG_COLOR_MASK_COLOR; /* grayscale not supported */
  243.  
  244.     if (surface->format->palette)
  245.         colortype |= PNG_COLOR_MASK_PALETTE;
  246.     else if (surface->format->Amask)
  247.         colortype |= PNG_COLOR_MASK_ALPHA;
  248.  
  249.     return colortype;
  250. }
  251.  
  252.  
  253. void png_user_warn(png_structp ctx, png_const_charp str)
  254. {
  255.     fprintf(stderr, "libpng: warning: %s\n", str);
  256. }
  257.  
  258.  
  259. void png_user_error(png_structp ctx, png_const_charp str)
  260. {
  261.     fprintf(stderr, "libpng: error: %s\n", str);
  262. }
  263.  
  264.  
  265. int png_save_surface(char *filename, SDL_Surface *surf)
  266. {
  267.     FILE *fp;
  268.     png_structp png_ptr;
  269.     png_infop info_ptr;
  270.     int i, colortype;
  271.     png_bytep *row_pointers;
  272.  
  273.     /* Opening output file */
  274.     fp = fopen(filename, "wb");
  275.     if (fp == NULL) {
  276.         perror("fopen error");
  277.         return -1;
  278.     }
  279.  
  280.     /* Initializing png structures and callbacks */
  281.     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
  282.         NULL, png_user_error, png_user_warn);
  283.     if (png_ptr == NULL) {
  284.         printf("png_create_write_struct error!\n");
  285.         return -1;
  286.     }
  287.  
  288.     info_ptr = png_create_info_struct(png_ptr);
  289.     if (info_ptr == NULL) {
  290.         png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
  291.         printf("png_create_info_struct error!\n");
  292.         exit(-1);
  293.     }
  294.  
  295.     if (setjmp(png_jmpbuf(png_ptr))) {
  296.         png_destroy_write_struct(&png_ptr, &info_ptr);
  297.         fclose(fp);
  298.         exit(-1);
  299.     }
  300.  
  301.     png_init_io(png_ptr, fp);
  302.  
  303.     colortype = png_colortype_from_surface(surf);
  304.     png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE,
  305.         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
  306.  
  307.     /* Writing the image */
  308.     png_write_info(png_ptr, info_ptr);
  309.     png_set_packing(png_ptr);
  310.  
  311.     row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*surf->h);
  312.     for (i = 0; i < surf->h; i++)
  313.         row_pointers[i] = (png_bytep)(Uint8 *)surf->pixels + i*surf->pitch;
  314.     png_write_image(png_ptr, row_pointers);
  315.     png_write_end(png_ptr, info_ptr);
  316.  
  317.     /* Cleaning out... */
  318.     free(row_pointers);
  319.     png_destroy_write_struct(&png_ptr, &info_ptr);
  320.     fclose(fp);
  321.  
  322.     return 0;
  323. }
Add Comment
Please, Sign In to add comment