From 263a017c4bc685eafc966692d931ddd53d5de6ab Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 24 Nov 2017 12:40:56 +0100 Subject: spa: close devices after enum Fix error reporting and close the devices after enumerating formats. --- spa/plugins/alsa/alsa-utils.c | 12 ++++++---- spa/plugins/v4l2/v4l2-utils.c | 54 +++++++++++++++++++++++++++++-------------- 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(¶ms); @@ -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) -- cgit v1.2.3