still problems to capture odd/even fields

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



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");
}

[Index of Archives]     [Linux DVB]     [Video Disk Recorder]     [Asterisk]     [Photo]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Free Photo Albums]     [Fedora Users]     [Fedora Women]     [ALSA Users]     [ALSA Devel]     [Linux USB]

Powered by Linux