diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2010-08-06 15:10:37 +0200 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2010-08-06 15:15:50 +0200 |
commit | ec31eb9d2562b6cc2af0d4eee8aeeed4fa2399eb (patch) | |
tree | ec5fce67523dcec8a4cbdfb5209b31f44fc71976 | |
parent | 5916c4de4d03290cd313f2bab9720ad9cd023992 (diff) |
Basic test pattern support for video output devices
Instead of filling video output buffers with 0s, generate and user a
test pattern.
If the -F argument is given, the test pattern is read from the specified
file. The file size must be at equal to or bigger than the image size.
If the -F argument is not given, a basic test pattern is generated
automatically. Every byte is set to the sum of its X and Y coordinates.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r-- | yavta.c | 75 |
1 files changed, 70 insertions, 5 deletions
@@ -42,8 +42,14 @@ struct device enum v4l2_memory memtype; unsigned int nbufs; unsigned int bufsize; - unsigned int imagesize; void **mem; + + unsigned int width; + unsigned int height; + unsigned int bytesperline; + unsigned int imagesize; + + void *pattern; }; static const char *v4l2_buf_type_name(enum v4l2_buf_type type) @@ -132,6 +138,7 @@ static int video_open(struct device *dev, const char *devname, int no_query) static void video_close(struct device *dev) { + free(dev->pattern); free(dev->mem); close(dev->fd); } @@ -187,6 +194,9 @@ static int video_get_format(struct device *dev) return ret; } + dev->width = fmt.fmt.pix.width; + dev->height = fmt.fmt.pix.height; + dev->bytesperline = fmt.fmt.pix.bytesperline; dev->imagesize = fmt.fmt.pix.bytesperline ? fmt.fmt.pix.sizeimage : 0; printf("Video format: %c%c%c%c (%08x) %ux%u\n", @@ -392,7 +402,7 @@ static int video_queue_buffer(struct device *dev, int index) if (dev->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { buf.bytesused = buf.length; - memset(dev->mem[buf.index], 0, buf.bytesused); + memcpy(dev->mem[buf.index], dev->pattern, buf.bytesused); } ret = ioctl(dev->fd, VIDIOC_QBUF, &buf); @@ -713,7 +723,56 @@ static int video_set_quality(struct device *dev, unsigned int quality) return 0; } -static int video_prepare_capture(struct device *dev, int nbufs, unsigned int offset) +static int video_load_test_pattern(struct device *dev, const char *filename) +{ + unsigned int x, y; + uint8_t *data; + int ret; + int fd; + + /* Load or generate the test pattern */ + dev->pattern = malloc(dev->bufsize); + if (dev->pattern == NULL) + return -ENOMEM; + + if (filename == NULL) { + if (dev->bytesperline == 0) { + printf("Compressed format detect and no test pattern filename given.\n" + "The test pattern can't be generated automatically.\n"); + return -EINVAL; + } + + data = dev->pattern; + + for (y = 0; y < dev->height; ++y) { + for (x = 0; x < dev->bytesperline; ++x) + *data++ = x + y; + } + + return 0; + } + + fd = open(filename, O_RDONLY); + if (fd == -1) { + printf("Unable to open test pattern file '%s': %s.\n", filename, + strerror(errno)); + return -errno; + } + + ret = read(fd, dev->pattern, dev->bufsize); + close(fd); + + if (ret != (int)dev->bufsize) { + printf("Test pattern file size %u doesn't match image size %u\n", + ret, dev->bufsize); + return -EINVAL; + } + + return 0; +} + +static int video_prepare_capture(struct device *dev, int nbufs, unsigned int offset, + const char *filename) { unsigned int i; int ret; @@ -722,6 +781,12 @@ static int video_prepare_capture(struct device *dev, int nbufs, unsigned int off if ((ret = video_alloc_buffers(dev, nbufs, offset)) < 0) return ret; + if (dev->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + ret = video_load_test_pattern(dev, filename); + if (ret < 0) + return ret; + } + /* Queue the buffers. */ for (i = 0; i < dev->nbufs; ++i) { ret = video_queue_buffer(dev, i); @@ -1114,7 +1179,7 @@ int main(int argc, char *argv[]) } } - if (!no_query) + if (!no_query || do_capture) video_get_format(&dev); /* Set the frame rate. */ @@ -1139,7 +1204,7 @@ int main(int argc, char *argv[]) return 1; } - if (video_prepare_capture(&dev, nbufs, userptr_offset)) { + if (video_prepare_capture(&dev, nbufs, userptr_offset, filename)) { video_close(&dev); return 1; } |