grab.c
上传用户:jxp0626
上传日期:2007-01-08
资源大小:102k
文件大小:6k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Unix_Linux

  1. /*
  2.  * Linux audio/video grab interface
  3.  * Copyright (c) 2000 Gerard Lantau.
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <netinet/in.h>
  22. #include <linux/videodev.h>
  23. #include <linux/soundcard.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <sys/ioctl.h>
  27. #include <sys/mman.h>
  28. #include <errno.h>
  29. #include <sys/time.h>
  30. #include <getopt.h>
  31. #include "mpegenc.h"
  32. long long gettime(void)
  33. {
  34.     struct timeval tv;
  35.     gettimeofday(&tv,NULL);
  36.     return (long long)tv.tv_sec * 1000000 + tv.tv_usec;
  37. }
  38. const char *v4l_device = "/dev/video";
  39. const char *audio_device = "/dev/dsp";
  40. /* v4l capture */
  41. static struct video_capability  video_cap;
  42. int video_fd = -1;
  43. UINT8 *video_buf, *picture_buf;
  44. struct video_mbuf gb_buffers;
  45. struct video_mmap gb_buf;
  46. struct video_audio audio;
  47. int gb_frame = 0;
  48. long long time_frame;
  49. int frame_rate;
  50. int use_mmap = 0;
  51. int v4l_init(int rate, int width, int height)
  52. {
  53.     frame_rate = rate;
  54.     video_fd = open(v4l_device, O_RDWR);
  55.     if (video_fd < 0) {
  56.         perror(v4l_device);
  57.         return -1;
  58.     }
  59.     
  60.     if (ioctl(video_fd,VIDIOCGCAP,&video_cap) < 0) {
  61.         perror("VIDIOCGCAP");
  62.         return -1;
  63.     }
  64.     
  65.     /* unmute audio */
  66.     ioctl(video_fd, VIDIOCGAUDIO, &audio);
  67.     audio.flags &= ~VIDEO_AUDIO_MUTE;
  68.     ioctl(video_fd, VIDIOCSAUDIO, &audio);
  69.     if (!(video_cap.type & VID_TYPE_CAPTURE)) {
  70.         /* try to use read based access */
  71.         struct video_window win;
  72.         int val;
  73.         win.x = 0;
  74.         win.y = 0;
  75.         win.width = width;
  76.         win.height = height;
  77.         win.chromakey = -1;
  78.         win.flags = 0;
  79.         ioctl(video_fd, VIDIOCSWIN, &win);
  80.         val = 1;
  81.         ioctl(video_fd, VIDIOCCAPTURE, &val);
  82.         video_buf = malloc( width * height * 2);
  83.         picture_buf = malloc( (width * height * 3) / 2);
  84.         use_mmap = 0;
  85.         return 0;
  86.     }
  87.     
  88.     if (ioctl(video_fd,VIDIOCGMBUF,&gb_buffers) < 0) {
  89.         perror("ioctl VIDIOCGMBUF");
  90.     }
  91.     
  92.     video_buf = mmap(0,gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0);
  93.     if ((unsigned char*)-1 == video_buf) {
  94.         perror("mmap");
  95.         return -1;
  96.     }
  97.     gb_frame = 0;
  98.     time_frame = gettime();
  99.     
  100.     /* start to grab the first frame */
  101.     gb_buf.frame = 1 - gb_frame;
  102.     gb_buf.height = height;
  103.     gb_buf.width = width;
  104.     gb_buf.format = VIDEO_PALETTE_YUV420P;
  105.     
  106.     if (ioctl(video_fd, VIDIOCMCAPTURE, &gb_buf) < 0) {
  107.         if (errno == EAGAIN)
  108.             fprintf(stderr,"Cannot Syncn");
  109.         else
  110.             perror("VIDIOCMCAPTURE");
  111.         return -1;
  112.     }
  113.     use_mmap = 1;
  114.     return 0;
  115. }
  116. /* test with read call and YUV422 stream */
  117. static int v4l_basic_read_picture(UINT8 *picture[3],
  118.                                   int width, int height,
  119.                                   int picture_number)
  120. {
  121.     int x, y;
  122.     UINT8 *p, *lum, *cb, *cr;
  123.     
  124.     if (read(video_fd, video_buf, width * height * 2) < 0)
  125.         perror("read");
  126.     picture[0] = picture_buf;
  127.     picture[1] = picture_buf + width * height;
  128.     picture[2] = picture_buf + (width * height) + (width * height) / 4;
  129.     
  130.     /* XXX: optimize */
  131.     lum = picture[0];
  132.     cb = picture[1];
  133.     cr = picture[2];
  134.     p = video_buf;
  135.     for(y=0;y<height;y+=2) {
  136.         for(x=0;x<width;x+=2) {
  137.             lum[0] = p[0];
  138.             cb[0] = p[1];
  139.             lum[1] = p[2];
  140.             cr[0] = p[3];
  141.             p += 4;
  142.             lum += 2;
  143.             cb++;
  144.             cr++;
  145.         }
  146.         for(x=0;x<width;x+=2) {
  147.             lum[0] = p[0];
  148.             lum[1] = p[2];
  149.             p += 4;
  150.             lum += 2;
  151.         }
  152.     }
  153.     return 0;
  154. }
  155. static int v4l_mm_read_picture(UINT8 *picture[3],
  156.                                int width, int height,
  157.                                int picture_number)
  158. {
  159.     UINT8 *ptr;
  160.     int size;
  161.     long long curtime;
  162.     /* wait based on the frame rate */
  163.     time_frame += 1000000 / frame_rate;
  164.     do {
  165.         curtime = gettime();
  166.     } while (curtime < time_frame);
  167.     
  168.     gb_buf.frame = gb_frame;
  169.     if (ioctl(video_fd, VIDIOCMCAPTURE, &gb_buf) < 0) {
  170. if (errno == EAGAIN)
  171.     fprintf(stderr,"Cannot Syncn");
  172. else
  173.             perror("VIDIOCMCAPTURE");
  174. return -1;
  175.     }
  176.     gb_frame = 1 - gb_frame;
  177.     if (ioctl(video_fd, VIDIOCSYNC, &gb_frame) < 0) {
  178.         if (errno != EAGAIN) {
  179.             perror("VIDIOCSYNC");
  180.         }
  181.     }
  182.     size = width * height;
  183.     ptr = video_buf + gb_buffers.offsets[gb_frame];
  184.     picture[0] = ptr;
  185.     picture[1] = ptr + size;
  186.     picture[2] = ptr + size + (size / 4);
  187.     
  188.     return 0;
  189. }
  190. int v4l_read_picture(UINT8 *picture[3],
  191.                      int width, int height,
  192.                      int picture_number)
  193. {
  194.     if (use_mmap) {
  195.         return v4l_mm_read_picture(picture, width, height, picture_number);
  196.     } else {
  197.         return v4l_basic_read_picture(picture, width, height, picture_number);
  198.     }
  199. }
  200. /* open audio device */
  201. int audio_open(int freq, int channels)
  202. {
  203.     int audio_fd, tmp, err;
  204.     audio_fd = open(audio_device,O_RDONLY);
  205.     if (audio_fd < 0) {
  206.         perror(audio_device);
  207.         return -1;
  208.     }
  209.     /* non blocking mode */
  210.     fcntl(audio_fd, F_SETFL, O_NONBLOCK);
  211. #if 0
  212.     tmp=(NB_FRAGMENTS << 16) | FRAGMENT_BITS;
  213.     err=ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
  214.     if (err < 0) {
  215.         perror("SNDCTL_DSP_SETFRAGMENT");
  216.     }
  217. #endif
  218.     /* always set to this size */
  219.     /* XXX: incorrect if big endian */
  220.     tmp=AFMT_S16_LE;
  221.     err=ioctl(audio_fd,SNDCTL_DSP_SETFMT,&tmp);
  222.     if (err < 0) {
  223.         perror("SNDCTL_DSP_SETFMT");
  224.     }
  225.     
  226.     tmp= (channels == 2);
  227.     err=ioctl(audio_fd,SNDCTL_DSP_STEREO,&tmp);
  228.     if (err < 0) {
  229.         perror("SNDCTL_DSP_STEREO");
  230.     }
  231.     
  232.     /* should be last */
  233.     tmp = freq;
  234.     err=ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
  235.     if (err < 0) {
  236.         perror("SNDCTL_DSP_SPEED");
  237.     }
  238.     return audio_fd;
  239. }