diff options
Diffstat (limited to 'v4l2-apps/lib/libv4l/libv4l2')
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4l2/Makefile | 6 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4l2/libv4l2.c | 135 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4l2/log.c | 6 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c | 27 |
4 files changed, 95 insertions, 79 deletions
diff --git a/v4l2-apps/lib/libv4l/libv4l2/Makefile b/v4l2-apps/lib/libv4l/libv4l2/Makefile index d8ac01c34..648d27c0c 100644 --- a/v4l2-apps/lib/libv4l/libv4l2/Makefile +++ b/v4l2-apps/lib/libv4l/libv4l2/Makefile @@ -1,7 +1,7 @@ -CPPFLAGS = -I../include -I../../../../linux/include +override CPPFLAGS += -I../include -I../../../include -fvisibility=hidden CFLAGS := -g -O1 -CFLAGS += -Wall -W -Wno-unused -Wpointer-arith -Wstrict-prototypes +CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes LIBS = -lpthread @@ -17,7 +17,7 @@ else V4L2_LIB = libv4l2.so V4L2_OBJS += ../libv4lconvert/libv4lconvert.so TARGETS += $(V4L2CONVERT) -CPPFLAGS += -fPIC +override CPPFLAGS += -fPIC endif ifeq ($(LIB_RELEASE),) diff --git a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c b/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c index a40ab4ffe..7029f69c3 100644 --- a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c +++ b/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c @@ -252,23 +252,54 @@ static int v4l2_queue_read_buffer(int index, int buffer_index) return 0; } -static int v4l2_dequeue_read_buffer(int index, int *bytesused) +static int v4l2_dequeue_and_convert(int index, struct v4l2_buffer *buf, + unsigned char *dest, int dest_size) { - int result; - struct v4l2_buffer buf; + const int max_tries = 10; + int result, tries = max_tries; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, &buf))) { - int saved_err = errno; - V4L2_LOG_ERR("dequeuing buf: %s\n", strerror(errno)); - errno = saved_err; + /* Make sure we have the real v4l2 buffers mapped */ + if ((result = v4l2_map_buffers(index))) return result; + + do { + if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, buf))) { + int saved_err = errno; + V4L2_LOG_ERR("dequeuing buf: %s\n", strerror(errno)); + errno = saved_err; + return result; + } + + devices[index].frame_queued &= ~(1 << buf->index); + + result = v4lconvert_convert(devices[index].convert, + &devices[index].src_fmt, &devices[index].dest_fmt, + devices[index].frame_pointers[buf->index], + buf->bytesused, dest ? dest : (devices[index].convert_mmap_buf + + buf->index * V4L2_FRAME_BUF_SIZE), dest_size); + + if (result < 0) { + int saved_err = errno; + + if(errno == EAGAIN) + V4L2_LOG("warning error while converting frame data: %s\n", + v4lconvert_get_error_message(devices[index].convert)); + else + V4L2_LOG_ERR("converting / decoding frame data: %s\n", + v4lconvert_get_error_message(devices[index].convert)); + + v4l2_queue_read_buffer(index, buf->index); + errno = saved_err; + } + tries--; + } while (result < 0 && errno == EAGAIN && tries); + + if (result < 0 && errno == EAGAIN) { + V4L2_LOG_ERR("got %d consecutive frame decode errors, last error: %s\n", + max_tries, v4lconvert_get_error_message(devices[index].convert)); } - devices[index].frame_queued &= ~(1 << buf.index); - *bytesused = buf.bytesused; - return buf.index; + return result; } static int v4l2_queue_read_buffers(int index) @@ -614,7 +645,8 @@ int v4l2_ioctl (int fd, unsigned long int request, ...) is_capture_request = 1; break; case VIDIOC_ENUM_FMT: - if (((struct v4l2_fmtdesc *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (((struct v4l2_fmtdesc *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && + (devices[index].flags & V4L2_ENABLE_ENUM_FMT_EMULATION)) is_capture_request = 1; break; case VIDIOC_TRY_FMT: @@ -663,9 +695,8 @@ int v4l2_ioctl (int fd, unsigned long int request, ...) if (stream_needs_locking) pthread_mutex_lock(&devices[index].stream_lock); - converting = devices[index].src_fmt.fmt.pix.pixelformat != - devices[index].dest_fmt.fmt.pix.pixelformat; - + converting = v4lconvert_needs_conversion(devices[index].convert, + &devices[index].src_fmt, &devices[index].dest_fmt); switch (request) { case VIDIOC_QUERYCAP: @@ -815,15 +846,16 @@ int v4l2_ioctl (int fd, unsigned long int request, ...) if ((result = v4l2_deactivate_read_stream(index))) break; - result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, buf); - if (result) { - V4L2_LOG_ERR("dequeing buffer: %s\n", strerror(errno)); + if (!converting) { + result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, buf); + if (result) { + int saved_err = errno; + V4L2_LOG_ERR("dequeuing buf: %s\n", strerror(errno)); + errno = saved_err; + } break; } - if (!converting) - break; - /* An application can do a DQBUF before mmap-ing in the buffer, but we need the buffer _now_ to write our converted data to it! */ @@ -844,23 +876,9 @@ int v4l2_ioctl (int fd, unsigned long int request, ...) } } - /* Make sure we have the real v4l2 buffers mapped before trying to - read from them */ - if ((result = v4l2_map_buffers(index))) - break; - - result = v4lconvert_convert(devices[index].convert, - &devices[index].src_fmt, &devices[index].dest_fmt, - devices[index].frame_pointers[buf->index], - buf->bytesused, - devices[index].convert_mmap_buf + - buf->index * V4L2_FRAME_BUF_SIZE, - V4L2_FRAME_BUF_SIZE); - if (result < 0) { - V4L2_LOG_ERR("converting / decoding frame data: %s\n", - v4lconvert_get_error_message(devices[index].convert)); + result = v4l2_dequeue_and_convert(index, buf, 0, V4L2_FRAME_BUF_SIZE); + if (result < 0) break; - } buf->bytesused = result; buf->m.offset = V4L2_MMAP_OFFSET_MAGIC | buf->index; @@ -901,22 +919,23 @@ int v4l2_ioctl (int fd, unsigned long int request, ...) } -ssize_t v4l2_read (int fd, void* buffer, size_t n) +ssize_t v4l2_read (int fd, void* dest, size_t n) { ssize_t result; - int index, bytesused = 0, frame_index; + int index; + struct v4l2_buffer buf; if ((index = v4l2_get_index(fd)) == -1) - return syscall(SYS_read, fd, buffer, n); + return syscall(SYS_read, fd, dest, n); pthread_mutex_lock(&devices[index].stream_lock); /* When not converting and the device supports read let the kernel handle it */ if ((devices[index].flags & V4L2_SUPPORTS_READ) && - devices[index].src_fmt.fmt.pix.pixelformat == - devices[index].dest_fmt.fmt.pix.pixelformat) { - result = syscall(SYS_read, fd, buffer, n); + !v4lconvert_needs_conversion(devices[index].convert, + &devices[index].src_fmt, &devices[index].dest_fmt)) { + result = syscall(SYS_read, fd, dest, n); goto leave; } @@ -931,26 +950,12 @@ ssize_t v4l2_read (int fd, void* buffer, size_t n) goto leave; } - if ((frame_index = v4l2_dequeue_read_buffer(index, &bytesused)) < 0) { - result = -1; - goto leave; - } - - /* ensure buffers are mapped before using them (they could have been - unmapped by a s_fmt ioctl) */ - if ((result = v4l2_map_buffers(index))) - goto leave; - - result = v4lconvert_convert(devices[index].convert, - &devices[index].src_fmt, &devices[index].dest_fmt, - devices[index].frame_pointers[frame_index], bytesused, - buffer, n); - - v4l2_queue_read_buffer(index, frame_index); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + result = v4l2_dequeue_and_convert(index, &buf, dest, n); - if (result < 0) - V4L2_LOG_ERR("converting / decoding frame data: %s\n", - v4lconvert_get_error_message(devices[index].convert)); + if (result >= 0) + v4l2_queue_read_buffer(index, buf.index); leave: pthread_mutex_unlock(&devices[index].stream_lock); @@ -988,8 +993,8 @@ void *v4l2_mmap(void *start, size_t length, int prot, int flags, int fd, buffer_index = offset & 0xff; if (buffer_index >= devices[index].no_frames || /* Got magic offset and not converting ?? */ - devices[index].src_fmt.fmt.pix.pixelformat == - devices[index].dest_fmt.fmt.pix.pixelformat) { + !v4lconvert_needs_conversion(devices[index].convert, + &devices[index].src_fmt, &devices[index].dest_fmt)) { errno = EINVAL; result = MAP_FAILED; goto leave; diff --git a/v4l2-apps/lib/libv4l/libv4l2/log.c b/v4l2-apps/lib/libv4l/libv4l2/log.c index 05f6c46d7..6237d55ec 100644 --- a/v4l2-apps/lib/libv4l/libv4l2/log.c +++ b/v4l2-apps/lib/libv4l/libv4l2/log.c @@ -25,6 +25,8 @@ #include <asm/types.h> /* end broken header workaround includes */ #include <linux/videodev2.h> +#include "libv4l2.h" +#include "libv4l2-priv.h" #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) @@ -116,7 +118,7 @@ void v4l2_log_ioctl(unsigned long int request, void *arg, int result) int pixfmt = fmt->fmt.pix.pixelformat; if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - fprintf(v4l2_log_file, " pixelformat: %c%c%c%c %dx%d\n", + fprintf(v4l2_log_file, " pixelformat: %c%c%c%c %ux%u\n", pixfmt & 0xff, (pixfmt >> 8) & 0xff, (pixfmt >> 16) & 0xff, @@ -136,7 +138,7 @@ void v4l2_log_ioctl(unsigned long int request, void *arg, int result) struct v4l2_requestbuffers *req = arg; fprintf(v4l2_log_file, " count: %u type: %d memory: %d\n", - req->count, req->type, req->memory); + req->count, (int)req->type, (int)req->memory); } break; } diff --git a/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c b/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c index f312828c6..e8756f338 100644 --- a/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c +++ b/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c @@ -27,6 +27,8 @@ #include <syscall.h> #include <fcntl.h> #include <string.h> +#include <sys/ioctl.h> +#include <sys/mman.h> /* These headers are not needed by us, but by linux/videodev2.h, which is broken on some systems and doesn't include them itself :( */ #include <sys/time.h> @@ -41,7 +43,13 @@ #error open/read/mmap is a prepocessor macro !! #endif -int open (const char *file, int oflag, ...) +#if __GNUC__ >= 4 +#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) +#else +#define LIBV4L_PUBLIC +#endif + +LIBV4L_PUBLIC int open (const char *file, int oflag, ...) { int fd; struct v4l2_capability cap; @@ -84,7 +92,7 @@ int open (const char *file, int oflag, ...) return fd; } -int open64(const char *file, int oflag, ...) +LIBV4L_PUBLIC int open64(const char *file, int oflag, ...) { int fd; @@ -107,17 +115,17 @@ int open64(const char *file, int oflag, ...) return fd; } -int close(int fd) +LIBV4L_PUBLIC int close(int fd) { return v4l2_close(fd); } -int dup(int fd) +LIBV4L_PUBLIC int dup(int fd) { return v4l2_dup(fd); } -int ioctl (int fd, unsigned long int request, ...) +LIBV4L_PUBLIC int ioctl (int fd, unsigned long int request, ...) { void *arg; va_list ap; @@ -129,24 +137,25 @@ int ioctl (int fd, unsigned long int request, ...) return v4l2_ioctl (fd, request, arg); } -ssize_t read (int fd, void* buffer, size_t n) +LIBV4L_PUBLIC ssize_t read (int fd, void* buffer, size_t n) { return v4l2_read (fd, buffer, n); } -void *mmap(void *start, size_t length, int prot, int flags, int fd, +LIBV4L_PUBLIC void *mmap(void *start, size_t length, int prot, int flags, int fd, __off_t offset) { return v4l2_mmap(start, length, prot, flags, fd, offset); } -void *mmap64(void *start, size_t length, int prot, int flags, int fd, +LIBV4L_PUBLIC void *mmap64(void *start, size_t length, int prot, int flags, int fd, __off64_t offset) { return v4l2_mmap(start, length, prot, flags, fd, offset); } -int munmap(void *start, size_t length) +LIBV4L_PUBLIC int munmap(void *start, size_t length) { return v4l2_munmap(start, length); } + |