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

📄 webcam.c

📁 camE 1.9 for Linux - camE is an imlib2 webcam grabber, annotator, and uploader.
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * (c) 1998-2000 Gerd Knorr * (c) 2000-2004 Tom Gilbert * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <math.h>#include <stdarg.h>#include <errno.h>#include <fcntl.h>#include <time.h>#include <sys/time.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/select.h>#include <signal.h>#include <X11/Xlib.h>#include <Imlib2.h>#include <giblib.h>#include <curl/types.h>#include <curl/curl.h>#include <curl/easy.h>#include <sys/types.h>#include <linux/videodev.h>#include <net/if.h>#include "parseconfig.h"#include "pwc-ioctl.h"#define VERSION "1.9"void camlog(char *fmt,         ...);char *ftp_host = "www";char *ftp_user = "webcam";char *ftp_pass = "xxxxxx";char *ftp_dir = "public_html/images";char *ftp_file = "webcam.jpeg";char *ftp_tmp = "uploading.jpeg";int ftp_debug = 0;char *temp_file = "/tmp/webcam.jpg";pid_t childpid = 0;int ftp_passive = 1;int ftp_do = 1;int ftp_upload_every = 1; /* default to upload every shot */int ftp_keepalive = 1;int ftp_delete_first = 0;char *scp_target = NULL;char *grab_device = "/dev/video0";char *grab_text = "";           /* strftime */char *action_pre_shot = NULL;char *action_post_shot = NULL;char *action_post_upload = NULL;char *grab_infofile = NULL;char *logfile = NULL;int grab_width = 320;int grab_height = 240;float grab_delay = 3.0;int grab_quality = 75;int lag_reduce = 5;int scp_timeout = 30;int text_r = 255;int text_g = 255;int text_b = 255;int text_a = 255;char *text_font = "arial/8";int title_r = 255;int title_g = 255;int title_b = 255;int title_a = 255;int bg_r = 0;int bg_g = 0;int bg_b = 0;int bg_a = 150;int close_dev = 0;int ftp_timeout = 30;int cam_contrast = 50;int cam_brightness = 50;int cam_hue = 50;int cam_colour = 50;int cam_whiteness = 50;int cam_framerate = 10;char *title_font = "arial/8";char *ttf_dir = "/usr/X11R6/lib/X11/fonts/TrueType";char *archive_ext = "jpg";char *grab_archive = NULL;int archive_subdirs = 0;    /* default to archive without    */                            /* subdirs                       */int archive_shot_every = 1;     /* default to archive every shot */char *archive_thumbnails_dir = NULL;int archive_thumbnails_create = 0; /* default is not to create archive thumbnails */int archive_thumbnails_width = 120;int archive_thumbnails_height = 90;char *grab_blockfile = NULL;char *upload_blockfile = NULL;char *grab_postprocess = NULL;char *title_text = NULL;gib_style *title_style = NULL;gib_style *text_style = NULL;char *title_style_file = NULL;char *text_style_file = NULL;char *overlay_file = NULL;Imlib_Image overlay_im = NULL;int overlay_x = 0, overlay_y = 0;Imlib_Font title_fn, text_fn;char *ftp_interface = "-";char *watch_interface = NULL;char *offline_image = NULL;int interface_active = 0;int device_palette;char *pwc_wb_mode = "auto";int pwc_wb_red = 50;int pwc_wb_blue = 50;int crop = 0;int crop_x = 0;int crop_y = 0;int crop_width = 0;int crop_height = 0;int scale = 0;int scale_width = 0;int scale_height = 0;int v_width[5] = { 128, 160, 176, 320, 640 };int v_height[5] = { 96, 120, 144, 240, 480 };int v_curr = -1;int v_force = 0;int bw_percent = 100;int delay_correct = 0;int reinit_device = 0;int flip_horizontal = 0;int flip_vertical = 0;int orientation = 0;int connections = 0;CURL *curl_handle = NULL;struct video_picture cam_pic;/* these work for v4l only, not v4l2 */int grab_input = 0;int grab_norm = VIDEO_MODE_PAL;static struct video_mmap grab_buf;static int grab_fd = -1;static int grab_size = 0;static unsigned char *grab_data = NULL;Imlib_Image convert_yuv420p_to_imlib2(unsigned char *mem,                                      int width,                                      int height);int execvp_with_timeout(int timeout,                        char *file,                        char **argv);void alarm_handler(int sig);int save_image(Imlib_Image image,               char *file);struct timeval add_timevals( struct timeval t1, struct timeval t2 ){  struct timeval tr;  tr.tv_usec = t1.tv_usec + t2.tv_usec;  tr.tv_sec = t1.tv_sec + t2.tv_sec + tr.tv_usec/1000000;  tr.tv_usec = tr.tv_usec%1000000;  return tr;}struct timeval sub_timevals( struct timeval t1, struct timeval t2 ){  struct timeval tr;  tr.tv_usec = t1.tv_usec - t2.tv_usec;  tr.tv_sec = t1.tv_sec - t2.tv_sec + t1.tv_usec/1000000;  while( tr.tv_usec<0 ){    tr.tv_sec-=1;    tr.tv_usec+=1000000;  }  return tr;}float float_timeval( struct timeval t ){  float f = 1e-6 * t.tv_usec;  f += t.tv_sec;  return f;}struct timeval timeval_float( float f ){  struct timeval tr;  tr.tv_sec = (time_t) floor(f);  f -= tr.tv_sec;  tr.tv_usec = (suseconds_t) round(1e6*f);  return tr;}voidclose_device(){  if (munmap(grab_data, grab_size) != 0) {    perror("munmap()");    exit(1);  }  grab_data = NULL;  if (close(grab_fd))    perror("close(grab_fd) ");  grab_fd = -1;}inttry_palette(int fd,            int pal,            int depth){  cam_pic.palette = pal;  cam_pic.depth = depth;  if (ioctl(fd, VIDIOCSPICT, &cam_pic) < 0)    return 0;  if (ioctl(fd, VIDIOCGPICT, &cam_pic) < 0)    return 0;  if (cam_pic.palette == pal)    return 1;  return 0;}intfind_palette(int fd,             struct video_mmap *vid){  if (try_palette(fd, VIDEO_PALETTE_RGB24, 24)) {    camlog("negotiated palette RGB24\n");    return VIDEO_PALETTE_RGB24;  }  if (try_palette(fd, VIDEO_PALETTE_YUV420P, 16)) {    camlog("negotiated palette YUV420P\n");    return VIDEO_PALETTE_YUV420P;  }  if (try_palette(fd, VIDEO_PALETTE_YUV420, 16)) {    camlog("negotiated palette YUV420\n");    return VIDEO_PALETTE_YUV420;  }  fprintf(stderr,          "No supported palette found, please report your device to the author\n");  exit(2);  return 0;}voidgrab_init(){  struct video_capability grab_cap;  struct video_channel grab_chan;  struct video_mbuf vid_mbuf;  int type;  if ((grab_fd = open(grab_device, O_RDWR)) == -1) {    fprintf(stderr, "open %s: %s\n", grab_device, strerror(errno));    exit(1);  }  if (ioctl(grab_fd, VIDIOCGCAP, &grab_cap) == -1) {    fprintf(stderr, "%s: no v4l device\n", grab_device);    exit(1);  }  if (ioctl(grab_fd, VIDIOCGPICT, &cam_pic) < 0)    perror("getting pic info");  cam_pic.contrast = 65535 * ((float) cam_contrast / 100);  cam_pic.brightness = 65535 * ((float) cam_brightness / 100);  cam_pic.hue = 65535 * ((float) cam_hue / 100);  cam_pic.colour = 65535 * ((float) cam_colour / 100);  cam_pic.whiteness = 65535 * ((float) cam_whiteness / 100);  if (ioctl(grab_fd, VIDIOCSPICT, &cam_pic) < 0)    perror("setting cam pic");  device_palette = find_palette(grab_fd, &grab_buf);  grab_buf.format = device_palette;  grab_buf.frame = 0;  grab_buf.width = grab_width;  grab_buf.height = grab_height;  ioctl(grab_fd, VIDIOCGMBUF, &vid_mbuf);  camlog("%s detected\n", grab_cap.name);  /* special philips features */  if (sscanf(grab_cap.name, "Philips %d webcam", &type) > 0) {    struct video_window vwin;    int shutter = -1;    int gain = -1;    struct pwc_whitebalance wb;    /* philips cam detected, maybe enable special features */    camlog("enabling pwc-specific features\n");    ioctl(grab_fd, VIDIOCGWIN, &vwin);    if (vwin.flags & PWC_FPS_MASK) {      /* Set new framerate */      vwin.flags &= ~PWC_FPS_FRMASK;      vwin.flags |= (cam_framerate << PWC_FPS_SHIFT);    }    /* Turning off snapshot mode */    vwin.flags &= ~(PWC_FPS_SNAPSHOT);    if (ioctl(grab_fd, VIDIOCSWIN, &vwin) < 0)      perror("trying to set extra pwc flags");    if (ioctl(grab_fd, VIDIOCPWCSAGC, &gain) < 0)      perror("trying to set gain");    if (ioctl(grab_fd, VIDIOCPWCSSHUTTER, &shutter) < 0)      perror("trying to set shutter");    wb.mode = PWC_WB_AUTO;    wb.manual_red = 50;    wb.manual_blue = 50;    if (!strcasecmp(pwc_wb_mode, "auto")) {      wb.mode = PWC_WB_AUTO;    } else if (!strcasecmp(pwc_wb_mode, "indoor")) {      wb.mode = PWC_WB_INDOOR;    } else if (!strcasecmp(pwc_wb_mode, "outdoor")) {      wb.mode = PWC_WB_OUTDOOR;    } else if (!strcasecmp(pwc_wb_mode, "fluorescent")) {      wb.mode = PWC_WB_FL;    } else if (!strcasecmp(pwc_wb_mode, "manual")) {      wb.mode = PWC_WB_MANUAL;      wb.manual_red = 65535 * ((float) pwc_wb_red / 100);      wb.manual_blue = 65535 * ((float) pwc_wb_blue / 100);    } else {      camlog("unknown pwc white balance mode '%s' ignored\n", pwc_wb_mode);    }    if (ioctl(grab_fd, VIDIOCPWCSAWB, &wb) < 0)      perror("trying to set pwc white balance mode");  }  /* set image source and TV norm */  grab_chan.channel = grab_input;  if (ioctl(grab_fd, VIDIOCGCHAN, &grab_chan) == -1) {    perror("ioctl VIDIOCGCHAN");    exit(1);  }  grab_chan.channel = grab_input;  grab_chan.norm = grab_norm;  if (ioctl(grab_fd, VIDIOCSCHAN, &grab_chan) == -1) {    perror("ioctl VIDIOCSCHAN");    exit(1);  }  /*   grab_size = grab_buf.width * grab_buf.height * 3; */  grab_size = vid_mbuf.size;  grab_data =    mmap(0, grab_size, PROT_READ | PROT_WRITE, MAP_SHARED, grab_fd, 0);  if ((grab_data == NULL) || (MAP_FAILED == grab_data)) {    fprintf(stderr,            "couldn't mmap vidcam. your card doesn't support that?\n");    exit(1);  }}/* This is a really simplistic approach. Speedups are welcomed. */Imlib_Imageconvert_yuv420p_to_imlib2(unsigned char *src,                          int width,                          int height){  int line, col;  int y, u, v, yy, vr = 0, ug = 0, vg = 0, ub = 0;  int r, g, b;  unsigned char *sy, *su, *sv;  Imlib_Image im;  DATA32 *data, *dest;  im = imlib_create_image(width, height);  imlib_context_set_image(im);  data = imlib_image_get_data();  dest = data;  sy = src;  su = sy + (width * height);  sv = su + (width * height / 4);  for (line = 0; line < height; line++) {    for (col = 0; col < width; col++) {      y = *sy++;      yy = y << 8;      u = *su - 128;      ug = 88 * u;      ub = 454 * u;      v = *sv - 128;      vg = 183 * v;      vr = 359 * v;      if ((col & 1) == 0) {        su++;        sv++;      }      r = (yy + vr) >> 8;      g = (yy - ug - vg) >> 8;      b = (yy + ub) >> 8;      if (r < 0)        r = 0;      if (r > 255)        r = 255;      if (g < 0)        g = 0;      if (g > 255)        g = 255;      if (b < 0)        b = 0;      if (b > 255)        b = 255;      *dest = (r << 16) | (g << 8) | b | 0xff000000;      dest++;

⌨️ 快捷键说明

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