summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2017-11-24 12:40:56 +0100
committerWim Taymans <wtaymans@redhat.com>2017-11-24 12:40:56 +0100
commit263a017c4bc685eafc966692d931ddd53d5de6ab (patch)
treec06be9be52c2439419ae2685cfd1559493417a03
parentf5f9acf84efd93ab5d994c666fc95b776b21bd58 (diff)
spa: close devices after enum
Fix error reporting and close the devices after enumerating formats.
-rw-r--r--spa/plugins/alsa/alsa-utils.c12
-rw-r--r--spa/plugins/v4l2/v4l2-utils.c54
2 files changed, 45 insertions, 21 deletions
diff --git a/spa/plugins/alsa/alsa-utils.c b/spa/plugins/alsa/alsa-utils.c
index 49b1a7f6..2c12f3d2 100644
--- a/spa/plugins/alsa/alsa-utils.c
+++ b/spa/plugins/alsa/alsa-utils.c
@@ -132,8 +132,10 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
next:
spa_pod_builder_init(&b, buffer, sizeof(buffer));
- if (*index > 0)
- return 0;
+ if (*index > 0) {
+ res = 0;
+ goto exit;
+ }
hndl = state->hndl;
snd_pcm_hw_params_alloca(&params);
@@ -199,10 +201,12 @@ spa_alsa_enum_format(struct state *state, uint32_t *index,
if ((res = spa_pod_filter(builder, result, fmt, filter)) < 0)
goto next;
+ res = 1;
+
+ exit:
if (!opened)
spa_alsa_close(state);
-
- return 1;
+ return res;
}
int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_t flags)
diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c
index 1ef20f9f..198e5271 100644
--- a/spa/plugins/v4l2/v4l2-utils.c
+++ b/spa/plugins/v4l2/v4l2-utils.c
@@ -38,49 +38,54 @@ static int xioctl(int fd, int request, void *arg)
return err;
}
+
static int spa_v4l2_open(struct impl *this)
{
struct port *port = &this->out_ports[0];
struct stat st;
struct props *props = &this->props;
+ int err;
if (port->opened)
return 0;
if (props->device[0] == '\0') {
spa_log_error(port->log, "v4l2: Device property not set");
- return -1;
+ return -EIO;
}
spa_log_info(port->log, "v4l2: Playback device is '%s'", props->device);
if (stat(props->device, &st) < 0) {
+ err = errno;
spa_log_error(port->log, "v4l2: Cannot identify '%s': %d, %s",
- props->device, errno, strerror(errno));
- return -1;
+ props->device, err, strerror(err));
+ return -err;
}
if (!S_ISCHR(st.st_mode)) {
spa_log_error(port->log, "v4l2: %s is no device", props->device);
- return -1;
+ return -ENODEV;
}
port->fd = open(props->device, O_RDWR | O_NONBLOCK, 0);
if (port->fd == -1) {
+ err = errno;
spa_log_error(port->log, "v4l2: Cannot open '%s': %d, %s",
- props->device, errno, strerror(errno));
- return -1;
+ props->device, err, strerror(err));
+ return -err;
}
if (xioctl(port->fd, VIDIOC_QUERYCAP, &port->cap) < 0) {
+ err = errno;
perror("QUERYCAP");
- return -1;
+ return -err;
}
if ((port->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
spa_log_error(port->log, "v4l2: %s is no video capture device", props->device);
- return -1;
+ return -ENODEV;
}
port->source.func = v4l2_on_fd_events;
@@ -98,6 +103,7 @@ static int spa_v4l2_buffer_recycle(struct impl *this, uint32_t buffer_id)
{
struct port *port = &this->out_ports[0];
struct buffer *b = &port->buffers[buffer_id];
+ int err;
if (!b->outstanding)
return 0;
@@ -106,8 +112,9 @@ static int spa_v4l2_buffer_recycle(struct impl *this, uint32_t buffer_id)
spa_log_trace(port->log, "v4l2 %p: recycle buffer %d", this, buffer_id);
if (xioctl(port->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) {
+ err = errno;
perror("VIDIOC_QBUF");
- return errno;
+ return -err;
}
return 0;
}
@@ -570,7 +577,7 @@ spa_v4l2_enum_format(struct impl *this,
filter, port->fmtdesc.index);
if (video_format == t->video_format.UNKNOWN)
- return 0;
+ goto enum_end;
info = find_format_info_by_media_type(t,
filter_media_type,
@@ -582,9 +589,10 @@ spa_v4l2_enum_format(struct impl *this,
port->fmtdesc.pixelformat = info->fourcc;
} else {
if ((res = xioctl(port->fd, VIDIOC_ENUM_FMT, &port->fmtdesc)) < 0) {
+ res = -errno;
if (errno != EINVAL)
perror("VIDIOC_ENUM_FMT");
- return 0;
+ goto exit;
}
}
port->next_fmtdesc = false;
@@ -604,8 +612,9 @@ spa_v4l2_enum_format(struct impl *this,
if (!(p = spa_pod_find_prop(filter, t->format_video.size)))
goto do_frmsize;
- if (p->body.value.type != SPA_POD_TYPE_RECTANGLE)
- return 0;
+ if (p->body.value.type != SPA_POD_TYPE_RECTANGLE) {
+ goto enum_end;
+ }
if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) {
const struct spa_rectangle *values =
@@ -625,8 +634,9 @@ spa_v4l2_enum_format(struct impl *this,
if (errno == EINVAL)
goto next_fmtdesc;
+ res = -errno;
perror("VIDIOC_ENUM_FRAMESIZES");
- return 0;
+ goto exit;
}
if (filter) {
struct spa_pod_prop *p;
@@ -707,6 +717,7 @@ spa_v4l2_enum_format(struct impl *this,
while (true) {
if ((res = xioctl(port->fd, VIDIOC_ENUM_FRAMEINTERVALS, &port->frmival)) < 0) {
+ res = -errno;
if (errno == EINVAL) {
port->frmsize.index++;
port->next_frmsize = true;
@@ -715,7 +726,7 @@ spa_v4l2_enum_format(struct impl *this,
break;
}
perror("VIDIOC_ENUM_FRAMEINTERVALS");
- return 0;
+ goto exit;
}
if (filter) {
struct spa_pod_prop *p;
@@ -727,7 +738,7 @@ spa_v4l2_enum_format(struct impl *this,
goto have_framerate;
if (p->body.value.type != SPA_POD_TYPE_FRACTION)
- return 0;
+ goto enum_end;
range = p->body.flags & SPA_POD_PROP_RANGE_MASK;
values = SPA_POD_BODY_CONST(&p->body.value);
@@ -795,7 +806,16 @@ spa_v4l2_enum_format(struct impl *this,
(*index)++;
- return 1;
+ res = 1;
+
+ exit:
+ spa_v4l2_close(this);
+
+ return res;
+
+ enum_end:
+ res = 0;
+ goto exit;
}
static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, bool try_only)