Hello, 

thank you for your hints, Gerd, but I have still problems with
bttv-0.8.38 and a patched 2.4.19-pre7 kernel.

If I use the v4l2-driver videodevX from http://www.thedirks.org/v4l2/
and the bttv2-driver from
http://bttv-v4l2.sourceforge.net/  it works (if I use 4 buffers) but
this site says that this drivers will be superseded by bttv-0.8.xx, so
I want to use 

If I use mp1e, version 1.9.1, with progressive filter mode (./mp1e m 1
-vv -F 6) I lose 50% of the frames (i.e. echo other field) with
bttv-0.8.38 and I get all fields with bttv2.

Does anybody has a working piece of code to capture both field with
bttv-0.8.xx?

I attach my code, maybe some bugs could be found out.

Thank you

  Bernd



> >               //vid_fmt.fmt.pix.flags |= V4L2_FMT_FLAG_INTERLACED;
> >               vid_fmt.fmt.pix.flags |= V4L2_FMT_FLAG_TOPFIELD;
> >               vid_fmt.fmt.pix.flags |= V4L2_FMT_FLAG_BOTFIELD;
> 
> Wrong.  Use v4l2_buffer->flags = V4L2_BUF_FLAG_(TOP|BOT)FIELD when
> queuing buffers.
> 
>   Gerd
> 
> --
> You can't please everybody.  And usually if you _try_ to please
> everybody, the end result is one big mess.
>                                 -- Linus Torvalds, 2002-04-20
>
/*
 *  $Id$
 *
 *  each_field_v4l2.c
 *    capture odd and even (TOP/BOTTOM) fields
 *
 *  Author: Bernd Blessmann
 *  Date: 2002-04-30
 *
 */


/* ---------------------------- includes --------------------------- */
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev.h>


/* ---------------------------- defines ---------------------------- */


/* ------------------------ static globals ------------------------- */


/* ------------------- static function prototypes ------------------ */
static void print_fmtpix(struct v4l2_format*);


/* ----------------------- public globals -------------------------- */


/* --------- public functions (prototypes in header only ----------- */


int main(int argc, char* argv[]) {
        int fd;                 /* file descriptor (video device) */
        struct v4l2_capability vid_cap;


        /* open device */
        if (argc != 2  ||  !argv[1]  ||  !*argv[1]) {
                fprintf(stderr, "usage:\t%s device\n", argv[0]);
                exit(1);
        }
        if ( (fd = open(argv[1], O_RDWR)) == -1 ) {
                fprintf(stderr, "unable to open video device %s: %s\n", argv[1], 
strerror(errno));
                exit(1);
        }

        /* query capabilities */
        if ( ioctl(fd, VIDIOC_QUERYCAP, &vid_cap) == -1 ) {
                perror("unable to query capabilities");
                close(fd);
                exit(1);
        }

        /* is it a capture device? */
        if (vid_cap.type != V4L2_TYPE_CAPTURE) {
                fprintf(stderr, "Not a capture device. Giving up\n");
                close(fd);
                exit(1);
        }

        /* can we use streaming? */
        if (!(vid_cap.flags & V4L2_FLAG_STREAMING)) {
                fprintf(stderr, "Device does not support streaming capture. Giving 
up\n");
                close(fd);
                exit(1);
        }

        /* start capture (with settings) */
        {
#define BUF_COUNT 4
                int i;
                int bufNr;
                struct v4l2_format vid_fmt;
                struct v4l2_requestbuffers vid_reqb;
                struct v4l2_buffer vid_buf[BUF_COUNT];
                int vid_type = V4L2_BUF_TYPE_CAPTURE;
                void* map[BUF_COUNT]; /* mapped memory */


                /* set input */
                i = 1;          /* Composite 1 */
                if ( ioctl(fd, VIDIOC_S_INPUT, &i) == -1 ) {
                        perror("VIDIOC_S_INPUT");
                        close(fd);
                        exit(1);
                }

                /* set up capture image format */
                /* query settings to init struct */
                vid_fmt.type = vid_type;
                if ( ioctl(fd, VIDIOC_G_FMT, &vid_fmt) == -1 ) {
                        perror("VIDIOC_G_FMT");
                        close(fd);
                        exit(1);
                }

                vid_fmt.fmt.pix.flags = 0x00;
                //vid_fmt.fmt.pix.flags |= V4L2_FMT_FLAG_INTERLACED;
                vid_fmt.fmt.pix.flags |= V4L2_FMT_FLAG_TOPFIELD;
                vid_fmt.fmt.pix.flags |= V4L2_FMT_FLAG_BOTFIELD;

                vid_fmt.fmt.pix.width = 384;
                vid_fmt.fmt.pix.height = 144;
                vid_fmt.fmt.pix.depth = 24;
                vid_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;

                if ( ioctl(fd, VIDIOC_S_FMT, &vid_fmt) == -1 ) {
                        perror("VIDIOC_S_FMT");
                        close(fd);
                        exit(1);
                }

                /* query settings */
                vid_fmt.type = vid_type;
                if ( ioctl(fd, VIDIOC_G_FMT, &vid_fmt) == -1 ) {
                        perror("VIDIOC_G_FMT");
                        close(fd);
                        exit(1);
                }
                printf("after get\n");
                print_fmtpix(&vid_fmt);

                /* allocate capture bufferrs */
                vid_reqb.count = BUF_COUNT;
                vid_reqb.type = vid_type;
                if ( ioctl(fd, VIDIOC_REQBUFS, &vid_reqb) == -1 ) {
                        perror("VIDIOC_REQBUFS");
                        close(fd);
                        exit(1);
                }
                if (vid_reqb.count != BUF_COUNT ||  vid_reqb.type != vid_type) {
                        fprintf(stderr, "VIDIOC_REQBUFS: got not what I wanted!\n");
                        close(fd);
                        exit(1);
                }

                for (bufNr = 0; bufNr < BUF_COUNT; bufNr++) {
                        vid_buf[bufNr].index = bufNr;
                        vid_buf[bufNr].type = vid_reqb.type;
                        if ( ioctl(fd, VIDIOC_QUERYBUF, &vid_buf[bufNr]) == -1 ) {
                                perror("VIDIOC_QUERYBUF");
                                close(fd);
                                exit(1);
                        }

                        /* memory map buffers */
                        map[bufNr] = mmap(0, vid_buf[bufNr].length, 
PROT_READ|PROT_WRITE, MAP_SHARED, fd, vid_buf[bufNr].offset);
                        if (MAP_FAILED == map[bufNr]) {
                                perror("unable to map memory");
                                close(fd);
                                exit(1);
                        }
                }

                /* streaming on */
                if ( ioctl(fd, VIDIOC_STREAMON, &vid_buf[0].type) == -1 ) {
                        perror("VIDIOC_STREAMON");
                        close(fd);
                        exit(1);
                }


                for (i = 0; i < 1000/BUF_COUNT; i++) {
                        /* capture buffers */
                        for (bufNr = 0; bufNr < BUF_COUNT; bufNr++) {
                                int n;
                                fd_set rdset;
                                struct timeval timeout;
                                static int lastSeq;
                                static long long lastStamp;
                                static int lastFieldType;


                                //if (lastFieldType == V4L2_BUF_FLAG_BOTFIELD) {
                                //      lastFieldType = vid_buf[bufNr].flags = 
V4L2_BUF_FLAG_TOPFIELD;
                                //} else {
                                //      lastFieldType = vid_buf[bufNr].flags = 
V4L2_BUF_FLAG_BOTFIELD;
                                //}
                                vid_buf[bufNr].flags = 0x00;
                                if ( ioctl(fd, VIDIOC_QBUF, &vid_buf[bufNr]) == -1 ) {
                                        fprintf(stderr, "buf %d: loop %d: ", bufNr, i);
                                        perror("VIDIOC_QBUF");
                                        close(fd);
                                        exit(1);
                                }
                                printf("Q%d   ", bufNr);

                                if ( i > 0  ||  bufNr >= (BUF_COUNT/2) ) {
                                        int otherBufNr = (bufNr + (BUF_COUNT/2)) % 
BUF_COUNT; 
                                        FD_ZERO (&rdset);
                                        FD_SET (fd, &rdset);

                                        timeout.tv_sec = 1;
                                        timeout.tv_usec = 0;
                                        n = select (fd + 1, &rdset, NULL, NULL, 
&timeout);
                                        if (n == -1) {
                                                perror("select error");
                                        } else if (n == 0) {
                                                fprintf (stderr, "select timeout buf 
%d\n", otherBufNr);
                                        } else if (FD_ISSET (fd, &rdset)) {
                                                if ( ioctl(fd, VIDIOC_DQBUF, 
&vid_buf[otherBufNr]) == -1 ) {
                                                        perror("VIDIOC_DQBUF");
                                                        close(fd);
                                                        exit(1);
                                                }
                                        }
                                        printf("  DQ%d", otherBufNr);
                                        printf("  buf%2d: seq%3u  ts%Ld", otherBufNr,
                                               vid_buf[otherBufNr].sequence, 
vid_buf[otherBufNr].timestamp);
                                        if (vid_buf[otherBufNr].flags & 
V4L2_BUF_FLAG_TOPFIELD) {
                                                printf("      TOPFIELD");
                                        }
                                        if (vid_buf[otherBufNr].flags & 
V4L2_BUF_FLAG_BOTFIELD) {
                                                printf("      BOTFIELD");
                                        }
                                        printf("\t\t");

                                        printf("-: seq %u  ts%f ms\n", 
vid_buf[otherBufNr].sequence - lastSeq,
                                               (vid_buf[otherBufNr].timestamp - 
lastStamp)/1000000.0);
                                        lastSeq = vid_buf[otherBufNr].sequence;
                                        lastStamp = vid_buf[otherBufNr].timestamp;
                                } else {
                                        printf("\n");
                                }
                        }
                }

                /* stream off */
                if ( ioctl(fd, VIDIOC_STREAMOFF, &vid_buf[0].type) == -1 ) {
                        perror("VIDIOC_STREAMOFF 0");
                        close(fd);
                        exit(1);
                }

                /* unmap memory */
                for (bufNr = 0; bufNr < BUF_COUNT; bufNr++) {
                        if ( munmap(map[bufNr], vid_buf[bufNr].length) == -1 ) {
                                perror("unable to unmap memory");
                                close(fd);
                                exit(1);
                        }
                }
#undef BUF_COUNT
        }

        /* close device */
        if ( close(fd) == -1 ) {
                perror("unable to close video device");
                exit(1);
        }

        return 0;
}


/* ---------------------------- statics ---------------------------- */
static void print_fmtpix(struct v4l2_format* fp)
{
        printf("   type:  %d\n", fp->type);
        printf("   flags: 0x%X\n", fp->fmt.pix.flags);
        printf("   width: %d\n", fp->fmt.pix.width);
        printf("   height: %d\n", fp->fmt.pix.height);
        printf("   depth: %d\n", fp->fmt.pix.depth);
        printf("   pixelformat: 0x%X\n", fp->fmt.pix.pixelformat);
        printf("   sizeimage: %d\n", fp->fmt.pix.sizeimage);
        printf("   INTERLACED: %s\n", (fp->fmt.pix.flags & V4L2_FMT_FLAG_INTERLACED)? 
"true": "false");
        printf("   TOPFIELD: %s\n", (fp->fmt.pix.flags & V4L2_FMT_FLAG_TOPFIELD)? 
"true": "false");
        printf("   BOTFIELD: %s\n", (fp->fmt.pix.flags & V4L2_FMT_FLAG_BOTFIELD)? 
"true": "false");
}

Reply via email to