#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>";
{"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 {
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;
}
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");
}
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);
} 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++;
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
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))
break;
}
}
- fclose(fp);
+ close(fd);
return 0;
}