diff options
Diffstat (limited to 'v4l2-apps')
-rw-r--r-- | v4l2-apps/libv4l2util/v4l2_driver.c | 12 | ||||
-rw-r--r-- | v4l2-apps/util/decode_tm6000.c | 195 |
2 files changed, 141 insertions, 66 deletions
diff --git a/v4l2-apps/libv4l2util/v4l2_driver.c b/v4l2-apps/libv4l2util/v4l2_driver.c index 94f826968..919119b6a 100644 --- a/v4l2-apps/libv4l2util/v4l2_driver.c +++ b/v4l2-apps/libv4l2util/v4l2_driver.c @@ -646,6 +646,9 @@ int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers) return 0; } +/* Returns <0, if error, 0 if nothing to read and <size>, if something + read + */ int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *rec_buf) { int ret; @@ -668,7 +671,7 @@ int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *rec_buf) default: perror ("dqbuf"); - return errno; + return -errno; } } prt_buf_info("DQBUF",&buf); @@ -677,19 +680,18 @@ int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *rec_buf) ret = rec_buf (&buf,&drv->bufs[buf.index]); - if (ret) { + if (ret<0) { v4l2_free_bufs(drv); return ret; } if (-1 == xioctl (drv->fd, VIDIOC_QBUF, &buf)) { perror ("qbuf"); - return errno; + return -errno; } - return 0; + return ret; } - int v4l2_start_streaming(struct v4l2_driver *drv) { uint32_t i; diff --git a/v4l2-apps/util/decode_tm6000.c b/v4l2-apps/util/decode_tm6000.c index 77920a593..d622360d2 100644 --- a/v4l2-apps/util/decode_tm6000.c +++ b/v4l2-apps/util/decode_tm6000.c @@ -21,6 +21,10 @@ #include <string.h> #include <argp.h> #include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> const char *argp_program_version="decode_tm6000 version 0.0.1"; const char *argp_program_bug_address="Mauro Carvalho Chehab <mchehab@infradead.org>"; @@ -30,12 +34,16 @@ const struct argp_option options[] = { {"device", 'd', "DEV", 0, "uses device for reading", 0}, {"output", 'o', "FILE", 0, "outputs raw stream to a file", 0}, {"input", 'i', "FILE", 0, "parses a file, instead of a device", 0}, + {"freq", 'f', "Freq", 0, "station frequency, in MHz (default is 193.25)", 0}, + {"nbufs", 'n', "quant",0, "number of video buffers", 0}, {"audio", 'a', 0, 0, "outputs audio on stdout", 0}, {"read", 'r', 0, 0, "use read() instead of mmap method", 0}, { 0, 0, 0, 0, 0, 0 } }; -static int debug=0, audio=0, use_mmap=1; +static char outbuf[692224]; +static int debug=0, audio=0, use_mmap=1, nbufs=4; +static float freq_mhz=193.25; static char *devname="/dev/video0"; static char *filename=NULL; static enum { @@ -76,6 +84,14 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) filename=arg; break; + case 'f': + freq_mhz=atof(arg); + break; + case 'n': + nbufs=atoi(arg); + if (nbufs<2) + nbufs=2; + break; default: return ARGP_ERR_UNKNOWN; } @@ -114,105 +130,150 @@ const char *tm6000_msg_type[]= { int recebe_buffer (struct v4l2_buffer *v4l2_buf, struct v4l2_t_buf *buf) { - fwrite (buf->start,buf->length,1,fout); - return 0; + dprintf("Received %d bytes\n",buf->length); +fflush(stdout); + memcpy (outbuf,buf->start,buf->length); + return buf->length; } -int read_mmap(struct v4l2_driver *drv) +int prepare_read (struct v4l2_driver *drv) { + struct v4l2_format fmt; double freq; + int rc; + + memset (drv,0,sizeof(*drv)); + + if (v4l2_open (devname, 1,drv)<0) { + perror ("Error opening dev"); + return -1; + } - freq=193.25 * 1000 * 1000; - v4l2_getset_freq (drv,V4L2_SET, &freq); + memset (&fmt,0,sizeof(fmt)); - printf("Preparing for frames...\n"); - fflush (stdout); - sleep(1); + uint32_t pixelformat=V4L2_PIX_FMT_TM6000; - v4l2_mmap_bufs(drv, 2); + if (v4l2_gettryset_fmt_cap (drv,V4L2_SET,&fmt, 720, 480, + pixelformat,V4L2_FIELD_ANY)) { + perror("set_input to tm6000 raw format"); + return -1; + } + + if (freq_mhz) { + freq=freq_mhz * 1000 * 1000; + rc=v4l2_getset_freq (drv,V4L2_SET, &freq); + if (rc<0) + printf ("Cannot set freq to %.3f MHz\n",freq_mhz); + } - v4l2_start_streaming(drv); + if (use_mmap) { + printf("Preparing for receiving frames on %d buffers...\n",nbufs); + fflush (stdout); + rc=v4l2_mmap_bufs(drv, nbufs); + if (rc<0) { + printf ("Cannot mmap %d buffers\n",nbufs); + return -1; + } + +// v4l2_stop_streaming(&drv); + rc=v4l2_start_streaming(drv); + if (rc<0) { + printf ("Cannot start streaming\n"); + return -1; + } + } printf("Waiting for frames...\n"); - while (1) { + + return 0; +} + +int read_stream (struct v4l2_driver *drv, int fd) +{ + if (use_mmap) { fd_set fds; struct timeval tv; int r; FD_ZERO (&fds); - FD_SET (drv->fd, &fds); + FD_SET (fd, &fds); /* Timeout. */ tv.tv_sec = 2; tv.tv_usec = 0; - r = select (drv->fd + 1, &fds, NULL, NULL, &tv); + r = select (fd + 1, &fds, NULL, NULL, &tv); if (-1 == r) { - if (EINTR == errno) - - perror ("select"); - return errno; + if (EINTR == errno) { + perror ("select"); + return -errno; + } } if (0 == r) { fprintf (stderr, "select timeout\n"); - return errno; + return -errno; } - if (v4l2_rcvbuf(drv, recebe_buffer)) - break; + return v4l2_rcvbuf(drv, recebe_buffer); + } else { + int size=read(fd, outbuf, sizeof(outbuf)); + return size; } + return 0; } +int read_char (struct v4l2_driver *drv, int fd) +{ + static int sizebuf=0; + static unsigned char *p=NULL; + unsigned char c; + + if (sizebuf<=0) { + sizebuf=read_stream(drv,fd); + if (sizebuf<=0) + return -1; + p=(unsigned char *)outbuf; + } + c=*p; + p++; + sizebuf--; + + return c; +} + int main (int argc, char*argv[]) { - FILE *fp; - unsigned char c, buf[TM6000_URB_MSG_LEN], img[720*2*480]; + int fd; + unsigned int i; + unsigned char buf[TM6000_URB_MSG_LEN], img[720*2*480]; unsigned int cmd, cpysize, pktsize, size, field, block, line, pos=0; unsigned long header=0; int linesize=720*2,skip=0; - struct v4l2_format fmt; struct v4l2_driver drv; argp_parse (&argp, argc, argv, 0, 0, 0); if (mode!=INPUT) { - if (v4l2_open (devname, 1,&drv)<0) { - perror ("Error opening dev"); - return -1; - } - fp=fdopen(drv.fd,"r"); - if (!fp) { - perror("error associating dev"); - return -1; - } - - memset (&fmt,0,sizeof(fmt)); - - uint32_t pixelformat=V4L2_PIX_FMT_TM6000; - - if (v4l2_gettryset_fmt_cap (&drv,V4L2_SET,&fmt, 720, 480, - pixelformat,V4L2_FIELD_ANY)) { - perror("set_input to tm6000 raw format"); + if (prepare_read (&drv)<0) return -1; - } - } + fd=drv.fd; + } else { + /*mode == INPUT */ - if (mode==INPUT) { - fp=fopen(filename,"r"); - if (!fp) { + fd=open(filename,O_RDONLY); + if (fd<0) { perror ("error opening a file for parsing"); return -1; } dprintf("file %s opened for parsing\n",filename); + use_mmap=0; } if (mode==OUTPUT) { - char outbuf[2<<18]; - fout=fopen(filename,"w"); if (!fout) { perror ("error opening a file to write"); @@ -220,15 +281,12 @@ int main (int argc, char*argv[]) } dprintf("file %s opened for output\n",filename); - if (use_mmap) { - return (read_mmap(&drv)); - } - do { - size=fread(outbuf,1, sizeof(outbuf), fp); - if (!size) { - fclose (fp); - return 0; + size=read_stream (&drv,fd); + + if (size<=0) { + close (fd); + return -1; } dprintf("writing %d bytes\n",size); fwrite(outbuf,1, size,fout); @@ -236,11 +294,18 @@ int main (int argc, char*argv[]) } while (1); } + while (1) { skip=0; header=0; do { - c=fgetc(fp); + int c; + c=read_char (&drv,fd); + if (c<0) { + perror("read"); + return -1; + } + header=(header>>8)&0xffffff; header=header|(c<<24); skip++; @@ -254,7 +319,15 @@ int main (int argc, char*argv[]) cmd = (header>>21) & 0x7; /* Read the remaining buffer */ - fread((char *)buf,sizeof(buf), 1, fp); + for (i=0;i<sizeof(buf);i++) { + int c; + c=read_char (&drv,fd); + if (c<0) { + perror("read"); + return -1; + } + buf[i]=c; + } /* FIXME: Mounts the image as field0+field1 * It should, instead, check if the user selected @@ -264,10 +337,10 @@ int main (int argc, char*argv[]) block*TM6000_URB_MSG_LEN; /* Prints debug info */ - dprintf("0x%08x (skip %d), %s size=%d, num=%d,line=%d, field=%d\n", + dprintf("0x%08x (skip %d), %s size=%d, line=%d, field=%d, block=%d\n", (unsigned int)header, skip, tm6000_msg_type[cmd], - size, block, line, field); + size, line, field, block); /* Don't allow to write out of the buffer */ if (pos+sizeof(buf) > sizeof(img)) @@ -286,6 +359,6 @@ int main (int argc, char*argv[]) break; } } - fclose(fp); + close(fd); return 0; } |