www.pudn.com > ffmpeg-0.3.4.rar > grab.c


/*
 * 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"

long long gettime(void)
{
    struct timeval tv;
    gettimeofday(&tv,NULL);
    return (long long)tv.tv_sec * 1000000 + tv.tv_usec;
}

const char *v4l_device = "/dev/video";
const char *audio_device = "/dev/dsp";

/* v4l capture */

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 (video_fd < 0) {
        perror(v4l_device);
        return -1;
    }
    
    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