That simple app reads data from SDR device using libv4l2 and writes it in float format to standard output. Stream is converted to complex float format by libv4l. sdr-fetch is based of v4l2grab v4l2 test app. Signed-off-by: Antti Palosaari <crope@xxxxxx> --- contrib/test/Makefile.am | 6 +- contrib/test/sdr_fetch.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 contrib/test/sdr_fetch.c diff --git a/contrib/test/Makefile.am b/contrib/test/Makefile.am index 80c7665..3332b63 100644 --- a/contrib/test/Makefile.am +++ b/contrib/test/Makefile.am @@ -7,7 +7,8 @@ noinst_PROGRAMS = \ v4l2grab \ driver-test \ stress-buffer \ - capture-example + capture-example \ + sdr-fetch if HAVE_X11 noinst_PROGRAMS += pixfmt-test @@ -45,6 +46,9 @@ stress_buffer_SOURCES = stress-buffer.c capture_example_SOURCES = capture-example.c +sdr_fetch_SOURCES = sdr_fetch.c +sdr_fetch_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la + ioctl-test.c: ioctl-test.h sync-with-kernel: diff --git a/contrib/test/sdr_fetch.c b/contrib/test/sdr_fetch.c new file mode 100644 index 0000000..477d11e --- /dev/null +++ b/contrib/test/sdr_fetch.c @@ -0,0 +1,221 @@ +/* + * SDR fetch + * + * Copyright (C) 2013 Antti Palosaari <crope@xxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <signal.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <argp.h> +#include <linux/videodev2.h> +#include "../../lib/include/libv4l2.h" + +/* signal handler to stop app */ +static int running; + +void signal_handler(int sig) +{ + running = 0; + return; +} + +#define CLEAR(x) memset(&(x), 0, sizeof(x)) + +struct buffer { + void *start; + size_t length; +}; + +static void xioctl(int fh, unsigned long int request, void *arg) +{ + int ret; + + do { + ret = v4l2_ioctl(fh, request, arg); + } while (ret == -1 && ((errno == EINTR) || (errno == EAGAIN))); + if (ret == -1) { + fprintf(stderr, "error %d, %s\n", errno, strerror(errno)); + exit(EXIT_FAILURE); + } +} + +static int stream(char *dev_name) +{ + struct v4l2_format fmt; + struct v4l2_buffer buf; + struct v4l2_requestbuffers req; + enum v4l2_buf_type type; + struct buffer *buffers; + struct timeval tv; + fd_set fds; + int ret, i, buffers_count, fd = -1; + + fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0); + if (fd < 0) { + perror("Cannot open device"); + exit(EXIT_FAILURE); + } + + /* ask float format from libv4l2 */ + CLEAR(fmt); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SDR_FLOAT; + xioctl(fd, VIDIOC_S_FMT, &fmt); + if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_SDR_FLOAT) { + perror("Libv4l didn't accept FLOAT format"); + exit(EXIT_FAILURE); + } + + /* request buffers */ + CLEAR(req); + req.count = 8; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + xioctl(fd, VIDIOC_REQBUFS, &req); + + buffers = calloc(req.count, sizeof(*buffers)); + + /* v4l2_mmap buffers */ + for (buffers_count = 0; buffers_count < req.count; buffers_count++) { + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = buffers_count; + xioctl(fd, VIDIOC_QUERYBUF, &buf); + + buffers[buffers_count].length = buf.length; + buffers[buffers_count].start = v4l2_mmap(NULL, buf.length, + PROT_READ | PROT_WRITE, MAP_SHARED, + fd, buf.m.offset); + + if (buffers[buffers_count].start == MAP_FAILED) { + perror("mmap"); + exit(EXIT_FAILURE); + } + } + + /* enqueue all memory mapped buffers */ + for (i = 0; i < buffers_count; i++) { + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + xioctl(fd, VIDIOC_QBUF, &buf); + } + + /* start streaming */ + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + xioctl(fd, VIDIOC_STREAMON, &type); + + /* data streaming */ + while (running) { + /* wait data arrives from device */ + do { + FD_ZERO(&fds); + FD_SET(fd, &fds); + + /* timeout */ + tv.tv_sec = 2; + tv.tv_usec = 0; + + ret = select(fd + 1, &fds, NULL, NULL, &tv); + } while ((ret == -1 && (errno == EINTR))); + if (ret == -1) { + perror("select"); + return errno; + } + + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + xioctl(fd, VIDIOC_DQBUF, &buf); + + /* write data to standard output */ + fwrite(buffers[buf.index].start, buf.bytesused, 1, stdout); + + xioctl(fd, VIDIOC_QBUF, &buf); + } + + /* stop streaming */ + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + xioctl(fd, VIDIOC_STREAMOFF, &type); + + /* v4l2_munmap buffers */ + for (i = buffers_count - 1; i >= 0; i--) + v4l2_munmap(buffers[i].start, buffers[i].length); + + free(buffers); + + v4l2_close(fd); + + return 0; +} + +const char *argp_program_version = "SDR fetch version " V4L_UTILS_VERSION; +const char *argp_program_bug_address = "Antti Palosaari <crope@xxxxxx>"; + +static const char doc[] = + "\n" + "Reads data from SDR device using libv4l2 and writes it in float format to standard output\n"; + +static const struct argp_option options[] = { + {"device", 'd', "DEV", 0, "SDR device (default: /dev/video0)", 0}, + { 0, 0, 0, 0, 0, 0 } +}; + +/* Static vars to store the parameters */ +static char *dev_name = "/dev/video0"; + +static error_t parse_opt(int k, char *arg, struct argp_state *state) +{ + switch (k) { + case 'd': + dev_name = arg; + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { + .options = options, + .parser = parse_opt, + .doc = doc, +}; + +int main(int argc, char **argv) +{ + /* arguments */ + argp_parse(&argp, argc, argv, 0, 0, 0); + + /* signal handler */ + running = 1; + signal(SIGQUIT, signal_handler); + signal(SIGINT, signal_handler); + + return stream(dev_name); +} -- 1.8.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html