summaryrefslogtreecommitdiff
path: root/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps/lib/libv4l/libv4l2/libv4l2.c')
-rw-r--r--v4l2-apps/lib/libv4l/libv4l2/libv4l2.c117
1 files changed, 61 insertions, 56 deletions
diff --git a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c b/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c
index dd43d938f..408f27398 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)
@@ -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,13 +919,14 @@ 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;
+ 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);
@@ -916,7 +935,7 @@ ssize_t v4l2_read (int fd, void* buffer, size_t n)
if ((devices[index].flags & V4L2_SUPPORTS_READ) &&
!v4lconvert_needs_conversion(devices[index].convert,
&devices[index].src_fmt, &devices[index].dest_fmt)) {
- result = syscall(SYS_read, fd, buffer, n);
+ 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);