/* * Linux audio/video grab interface * Copyright (c) 2000 Gerard Lantau. * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "mpegenc.h" #include "mpegvideo.h" long long gettime(void) { struct timeval tv; gettimeofday(&tv,NULL); return (long long)tv.tv_sec * 1000000 + tv.tv_usec; } /* v4l capture */ const char *v4l_device = "/dev/video"; static struct video_capability video_cap; int video_fd = -1; UINT8 *video_buf, *picture_buf; struct video_mbuf gb_buffers; struct video_mmap gb_buf; struct video_audio audio; int gb_frame = 0; long long time_frame; int frame_rate; int use_mmap = 0; int v4l_init(int rate, int width, int height) { frame_rate = rate; video_fd = open(v4l_device, O_RDWR); if (ioctl(video_fd,VIDIOCGCAP,&video_cap) < 0) { perror("VIDIOCGCAP"); return -1; } /* unmute audio */ ioctl(video_fd, VIDIOCGAUDIO, &audio); audio.flags &= ~VIDEO_AUDIO_MUTE; ioctl(video_fd, VIDIOCSAUDIO, &audio); if (!(video_cap.type & VID_TYPE_CAPTURE)) { /* try to use read based access */ struct video_window win; int val; win.x = 0; win.y = 0; win.width = width; win.height = height; win.chromakey = -1; win.flags = 0; ioctl(video_fd, VIDIOCSWIN, &win); val = 1; ioctl(video_fd, VIDIOCCAPTURE, &val); video_buf = malloc( width * height * 2); picture_buf = malloc( (width * height * 3) / 2); use_mmap = 0; return 0; } if (ioctl(video_fd,VIDIOCGMBUF,&gb_buffers) < 0) { perror("ioctl VIDIOCGMBUF"); } video_buf = mmap(0,gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0); if ((unsigned char*)-1 == video_buf) { perror("mmap"); return -1; } gb_frame = 0; time_frame = gettime(); /* start to grab the first frame */ gb_buf.frame = 1 - gb_frame; gb_buf.height = height; gb_buf.width = width; gb_buf.format = VIDEO_PALETTE_YUV420P; if (ioctl(video_fd, VIDIOCMCAPTURE, &gb_buf) < 0) { if (errno == EAGAIN) fprintf(stderr,"Cannot Sync\n"); else perror("VIDIOCMCAPTURE"); return -1; } use_mmap = 1; return 0; } /* test with read call and YUV422 stream */ static int v4l_basic_read_picture(UINT8 *picture[3], int width, int height, int picture_number) { int x, y; UINT8 *p, *lum, *cb, *cr; if (read(video_fd, video_buf, width * height * 2) < 0) perror("read"); picture[0] = picture_buf; picture[1] = picture_buf + width * height; picture[2] = picture_buf + (width * height) + (width * height) / 4; /* XXX: optimize */ lum = picture[0]; cb = picture[1]; cr = picture[2]; p = video_buf; for(y=0;y