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

📄 bgrab.c

📁 一个很好用的MPEG1/4的开源编码器的应用程序
💻 C
字号:
/*    Library: Threaded BTTV Grabbing with triple buffering    Copyright (C) 1999  A. Schiffler    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    To contact the author try these:    Andreas Schiffler,     ZKM, Lorezstr. 19, 76135 Karlsruhe, Germany    schiffler@zkm.de*/#include "bgrab.h"/* NOTE: Requires BTTV compatible framegrabber card. *//* Routine to get the time as float */double timeGet(void){  struct timeval tv;  double curtime;    /* get wallclock time */  gettimeofday(&tv, NULL);  curtime=(double)tv.tv_sec+1.0e-6*(double)tv.tv_usec;  return (curtime); }/* Call for each frame to get FPS calculation */void calc_fps(struct fgdevice *fg){ double curtime;  /* Check interval */ if (fg->fps_update_interval<1) {  fg->fps=0.0; } else {  if ( (fg->framecount<0) || (fg->framecount>=fg->fps_update_interval)) {   /* Initialize counter */   fg->framecount=0;   fg->lasttime=timeGet();   fg->fps=0.0;  } else {   fg->framecount++;   if (fg->framecount==fg->fps_update_interval) {    curtime=timeGet();    fg->fps=(double)fg->framecount/(curtime-fg->lasttime);    fg->lasttime=curtime;    fg->framecount=0;   }  } }  }/* Set the interval (in frames) after which the fps counter is updated */void fg_set_fps_interval(struct fgdevice *fg, int interval){ fg->fps_update_interval=interval; fg->framecount=-1;}/* Return fps */double fg_get_fps(struct fgdevice *fg){ return(fg->fps);} /* Prints device specific information to stderr */int fg_print_info(struct fgdevice *fg){ struct video_capability video_caps; struct video_channel video_chnl; struct video_audio video_aud; char BooleanText[2][5]={"YES\0","NO \0"}; int max_tuner; int i;  if (ioctl (fg->video_dev, VIDIOCGCAP, &video_caps) == -1) {  perror ("ioctl (VIDIOCGCAP)");  return(-1); } else {    /* List capabilities */    fprintf (stderr,"Device Info: ");  fprintf (stderr,"%s\n",video_caps.name);  fprintf (stderr," Can capture ... : %s  ",BooleanText[((video_caps.type & VID_TYPE_CAPTURE) == 0)]);  fprintf (stderr," Can clip ...... : %s  ",BooleanText[((video_caps.type & VID_TYPE_CLIPPING) == 0)]);  fprintf (stderr," Channels ...... : %i\n",video_caps.channels);  fprintf (stderr," Has tuner ..... : %s  ",BooleanText[((video_caps.type & VID_TYPE_TUNER) == 0)]);  fprintf (stderr," Ovl overwrites  : %s  ",BooleanText[((video_caps.type & VID_TYPE_FRAMERAM) == 0)]);  fprintf (stderr," Audio devices . : %i\n",video_caps.audios);  fprintf (stderr," Has teletext .. : %s  ",BooleanText[((video_caps.type & VID_TYPE_TELETEXT) == 0)]);  fprintf (stderr," Can scale ..... : %s  ",BooleanText[((video_caps.type & VID_TYPE_SCALES) == 0)]);  fprintf (stderr," Width min-max . : %i-%i\n",video_caps.minwidth,video_caps.maxwidth);  fprintf (stderr," Can overlay ... : %s  ",BooleanText[((video_caps.type & VID_TYPE_OVERLAY) == 0)]);  fprintf (stderr," Monochrome .... : %s  ",BooleanText[((video_caps.type & VID_TYPE_MONOCHROME) == 0)]);  fprintf (stderr," Height min-max  : %i-%i\n",video_caps.minheight,video_caps.maxheight);    fprintf (stderr," Can chromakey . : %s  ",BooleanText[((video_caps.type & VID_TYPE_CHROMAKEY) == 0)]);  fprintf (stderr," Can subcapture  : %s\n",BooleanText[((video_caps.type & VID_TYPE_SUBCAPTURE) == 0)]);    /* List input channels */    max_tuner=0;  for (i=0; i<video_caps.channels; i++) {   video_chnl.channel = i;   if (ioctl (fg->video_dev, VIDIOCGCHAN, &video_chnl) == -1) {    perror ("ioctl (VIDIOCGCHAN)");    return(-1);   } else {    fprintf (stderr," Channel %i: %s ",i,video_chnl.name);    if ((video_chnl.type & VIDEO_TYPE_TV)==0) {     fprintf (stderr,"(camera input)\n");    } else {     fprintf (stderr,"(TV input)\n");    }     fprintf (stderr,"  Tuners : %i  ",video_chnl.tuners);    if (video_chnl.tuners>max_tuner) max_tuner=video_chnl.tuners;     fprintf (stderr,"  Has audio : %s\n",BooleanText[((video_chnl.flags & VIDEO_VC_AUDIO) == 0)]);   }  }    /* Audio channels */  for (i=0; i<video_caps.audios; i++) {   video_aud.audio=i;   if (ioctl (fg->video_dev, VIDIOCGAUDIO, &video_aud) == -1) {    perror ("ioctl (VIDIOCGAUDIO)");    return(-1);   } else {    fprintf (stderr," Audio %i: %s\n",i,video_aud.name);    fprintf (stderr,"  Controllable: ");    if ((video_aud.flags & VIDEO_AUDIO_MUTABLE) != 0) fprintf (stderr,"Muting ");    if ((video_aud.flags & VIDEO_AUDIO_VOLUME) != 0) fprintf (stderr,"Volume ");    if ((video_aud.flags & VIDEO_AUDIO_BASS) != 0) fprintf (stderr,"Bass ");    if ((video_aud.flags & VIDEO_AUDIO_TREBLE) != 0) fprintf (stderr,"Treble ");    fprintf (stderr,"\n");   }   }  /* Retrieve sizes and offsets */  if (ioctl (fg->video_dev, VIDIOCGMBUF, &fg->vid_mbuf) == -1) {   perror ("ioctl (VIDIOCGMBUF)");   return(-1);  }  /* Print memory info */  fprintf (stderr,"Memory Map of %i frames: %i bytes\n",fg->vid_mbuf.frames,fg->vid_mbuf.size);  for (i=0; i<fg->vid_mbuf.frames; i++) {   fprintf (stderr," Offset of frame %i: %i\n",i,fg->vid_mbuf.offsets[i]);  } }  return(0);}/* Read card settings */int fg_get_setting(struct fgdevice *fg, int which_setting){ struct video_picture video_pict;  if (ioctl (fg->video_dev, VIDIOCGPICT, &video_pict) == -1) {  perror ("ioctl (VIDIOCGPICT)");  return(-1); } else {  switch (which_setting) {   case SETTING_BRIGHTNESS:    return(video_pict.brightness);    break;   case SETTING_HUE:    return(video_pict.hue);    break;   case SETTING_COLOUR:    return(video_pict.colour);    break;   case SETTING_CONTRAST:    return(video_pict.contrast);    break;  }  } return(-1);}/* Adjust card settings */int fg_set_setting(struct fgdevice *fg, int which_setting, int value){ struct video_picture video_pict;  if (ioctl (fg->video_dev, VIDIOCGPICT, &video_pict) == -1) {  perror ("ioctl (VIDIOCGPICT)");  return(-1); } else {  switch (which_setting) {   case SETTING_BRIGHTNESS:    video_pict.brightness=value;    break;   case SETTING_HUE:    video_pict.hue=value;    break;   case SETTING_COLOUR:    video_pict.colour=value;    break;   case SETTING_CONTRAST:    video_pict.contrast=value;    break;  }   if (ioctl (fg->video_dev, VIDIOCSPICT, &video_pict) == -1) {   perror ("ioctl (VIDIOCSPICT)");   return(-1);  }  } return(0);}/* Set the input channel on card */int fg_set_channel(struct fgdevice *fg, int channel){ struct video_capability video_cap; struct video_channel video_chan; /* Query for number of channels */ if (ioctl (fg->video_dev, VIDIOCGCAP, &video_cap) == -1) {  perror ("ioctl (VIDIOCGCAP)");  return(-1); }  /* Clip channel to allowed range */ if (channel<0) {  channel=0; } else {  video_cap.channels--;  if (channel>video_cap.channels) channel=video_cap.channels; } /* Set channel number */ video_chan.channel= channel; if (ioctl (fg->video_dev, VIDIOCSCHAN, &video_chan) == -1) {  perror ("ioctl (VIDIOCSCHAN)"); }  return(0);}/* Set the input channel on card */int fg_set_mode(struct fgdevice *fg, int mode){ struct video_capability video_cap; struct video_channel video_chan; struct video_tuner tuner; /* Set tuner mode */ tuner.tuner=0; tuner.mode=mode; if (ioctl (fg->video_dev, VIDIOCSTUNER, &tuner) == -1) {  perror ("ioctl (VIDIOCSTUNER)"); } return(0);}/* Self running thread that grabbs all images */void * grab_images_thread (struct fgdevice *fg){ /* Loop ... grabbing images */ while (1) {  /* Lock buffers and state */  pthread_mutex_lock(&fg->buffer_mutex);  /* Advance grab-frame number */  fg->current_grab_number=((fg->current_grab_number + 1) % 2);  /* Unlock buffers and state */  pthread_mutex_unlock(&fg->buffer_mutex);  /* Wait for next image in the sequence to complete grabbing */  if (ioctl (fg->video_dev, VIDIOCSYNC, &fg->vid_mmap[fg->current_grab_number]) == -1) {   perror ("VIDIOCSYNC");   fg->grabbing_active=0;   pthread_cond_signal(&fg->buffer_cond);   return((void *)&error_exit_status);  }  /* Issue new grab command for this buffer */  if (ioctl (fg->video_dev, VIDIOCMCAPTURE, &fg->vid_mmap[fg->current_grab_number]) == -1) {   perror ("VIDIOCMCAPTURE");   fg->grabbing_active=0;   pthread_cond_signal(&fg->buffer_cond);   return((void *)&error_exit_status);  }  /* Lock buffers and state */  pthread_mutex_lock(&fg->buffer_mutex);  /* Announce that a new frame is available */  fg->have_new_frame=1;  /* Unlock buffers and state */  pthread_mutex_unlock(&fg->buffer_mutex);  /* Signal potentially waiting main thread */  pthread_cond_signal(&fg->buffer_cond);    }}/* Initialize grabber and start grabbing-thread */int fg_start_grab_image (struct fgdevice *fg, int width, int height, int format){ int i; int depth;  /* Store variables in structure */ fg->width=width; fg->height=height; fg->format=format;  /* Retrieve buffer size and offsets */ if (ioctl (fg->video_dev, VIDIOCGMBUF, &fg->vid_mbuf) == -1) {  perror ("ioctl (VIDIOCGMBUF)");  return(-1); }  /* Map grabber memory unti user space */ fg->video_map = (char *) mmap (0, fg->vid_mbuf.size, PROT_READ|PROT_WRITE,MAP_SHARED,fg->video_dev,0); if ((unsigned char *)-1 == (unsigned char *)fg->video_map) {  perror ("mmap()");  return(-1); } /* Determine depth from format */ depth=2; switch (format) {  case VIDEO_PALETTE_GREY:   depth=1;   break;  case VIDEO_PALETTE_RGB565:  case VIDEO_PALETTE_YUV411P:  case VIDEO_PALETTE_YUV420P:  case VIDEO_PALETTE_YUV422P:   depth=2;   break;  case VIDEO_PALETTE_RGB32:   depth=4;   break;  default:   fprintf (stderr,"Unknown format.\n");   return(-1);   break;  } /* Generate mmap records */ for (i=0; i<2; i++) {  fg->vid_mmap[i].format = format;  fg->vid_mmap[i].frame  = i;  fg->vid_mmap[i].width  = width;  fg->vid_mmap[i].height = height; }   /* Calculate framebuffer size and allocate memory for user frames */ fg->image_pixels=width*height; fg->image_size=fg->image_pixels*depth; if ((fg->current_image=malloc(fg->image_size))==NULL) {  perror ("malloc()");  return(-1); }    /* Initiate capture for frames */ for (i=0; i<2; i++) {  if (ioctl (fg->video_dev, VIDIOCMCAPTURE, &fg->vid_mmap[i]) == -1) {   perror ("VIDIOCMCAPTURE");   return(-1);  } }  /* Reset grab counter variables */ fg->current_grab_number=0; fg->totalframecount=0; fg->have_new_frame=0;   /* Initialize mutex */ if (pthread_mutex_init(&fg->buffer_mutex, NULL)==-1) {  perror("pthread_mutex_init()");  return(-1); }  /* Initialize conditional */ if (pthread_cond_init(&fg->buffer_cond, NULL)==-1) {  perror("pthread_cond_init()");  return(-1); }  /* Start grabbing thread */ if (pthread_create(&fg->grab_thread,NULL,(void * (*)(void *)) grab_images_thread,fg)==-1) {  perror ("pthread_create()");  return(-1); }  /* Set flag */ fg->grabbing_active=1;  return(0);}/* Stop grabbing thread */int fg_stop_grab_image(struct fgdevice *fg){ /* Set flag */ fg->grabbing_active=0;  /* Stop grabbing thread */ if (pthread_cancel(fg->grab_thread)==-1) {  perror("pthread_cancel()");  return(-1); }  /* Free image buffers */ free(fg->current_image); fg->current_image=NULL; return(0);}/* Get last image, lock to be processed */ void * fg_get_next_image(struct fgdevice *fg){ /* Check if we are grabbing */ if (fg->grabbing_active) {  /* Increase counter */  fg->totalframecount++;     /* Lock buffers and state */  pthread_mutex_lock(&fg->buffer_mutex);    /* Check if a new frame is available */  if (!fg->have_new_frame) {   /* Wait for signal - unlocking mutex in the process */   pthread_cond_wait(&fg->buffer_cond,&fg->buffer_mutex);  }  /* Copy frame from other-than-grab framebuffer */  memcpy (fg->current_image,&fg->video_map[fg->vid_mbuf.offsets[(fg->current_grab_number+1) % 2]],fg->image_size);  /* Mark frame as used */  fg->have_new_frame=0;    /* Unlock buffers and state */  pthread_mutex_unlock(&fg->buffer_mutex);   /* FPS calculation */  calc_fps(fg);   } else {  /* No grabbing */  fg->current_image=NULL; }   /* Return pointer */ return (fg->current_image);}/* Open framegrabber device */int fg_open_device (struct fgdevice *fg, char *devicename){                                                                  int i,r,g,b; unsigned short *curypos; unsigned char *currgbpos; unsigned short us; /* Open the video4linux device */ fg->video_dev = open (devicename, O_RDWR); if (fg->video_dev == -1) {  perror("open()");  return (-1); }  /* Reset variables */ fg->grabbing_active=0; fg->width=-1; fg->height=-1; fg->format=-1; fg->input=-1; fg->image_size=-1; fg->image_pixels=-1; fg->fps_update_interval=-1;  /* Initialize color space conversion tables */ /* Y 8bit to RGB 16bit */ if ((fg->y8_to_rgb565=(unsigned short *)malloc(256*sizeof(short)))==NULL) {  perror("malloc"); } curypos=fg->y8_to_rgb565; for (i=0; i<256; i++) {    *curypos=((i >> 3) << 11 ) | ((i >> 2) << 5) | (i >> 3);  curypos++;  }  /* RGB 16 bit to Y 8bit */ if ( (fg->rgb565_to_y8=(unsigned char *)malloc(64*1024*sizeof(char)))==NULL) {  perror("malloc"); } currgbpos=fg->rgb565_to_y8;   for (i=0; i<(64*1024); i++) {  us=(unsigned short)i;  r=(us >> 11);  g=((us >> 5) & 63);  b=(us & 31);  *currgbpos=(r*2450+g*2404+b*934)/1024;            currgbpos++; } return(0);}/* Enable/disable audio */int fg_set_audio (struct fgdevice *fg, int vol){  struct video_audio       audio;   audio.audio = 0;  audio.volume = vol;  audio.flags = (vol)?VIDEO_AUDIO_VOLUME:VIDEO_AUDIO_MUTE;    if (ioctl (fg->video_dev, VIDIOCSAUDIO, &audio) == -1) {    perror ("VIDIOCSAUDIO");    return(-1);  }  return(1);}/* Close framegrabber device */int fg_close_device (struct fgdevice *fg){ /* Free allocated memory */ free(fg->current_image); free(fg->y8_to_rgb565); free(fg->rgb565_to_y8); /* Close video4linux device */ return(close(fg->video_dev));}

⌨️ 快捷键说明

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