From 1ca771305731664200738f25f936d5051ef97b15 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 8 May 2020 17:52:30 +0200 Subject: [PATCH] implement NEAREST flag when the NEAREST flag is set and the param could not be completely set, set_param should return 1 to indicate this. --- spa/plugins/alsa/alsa-pcm.c | 15 ++++++++------- spa/plugins/v4l2/v4l2-source.c | 2 +- spa/plugins/v4l2/v4l2-utils.c | 21 ++++++++++++--------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c index c3c170abe..f27e2a9e9 100644 --- a/spa/plugins/alsa/alsa-pcm.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -404,6 +404,7 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_ struct spa_audio_info_raw *info = &fmt->info.raw; snd_pcm_t *hndl; unsigned int periods; + bool match = true; if ((err = spa_alsa_open(state)) < 0) return err; @@ -439,10 +440,10 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_ if (rchannels != info->channels) { spa_log_warn(state->log, NAME" %p: Channels doesn't match (requested %u, get %u", state, info->channels, rchannels); - if (flags & SPA_NODE_PARAM_FLAG_NEAREST) - info->channels = rchannels; - else + if (!SPA_FLAG_IS_SET(flags, SPA_NODE_PARAM_FLAG_NEAREST)) return -EINVAL; + info->channels = rchannels; + match = false; } /* set the stream rate */ @@ -451,10 +452,10 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_ if (rrate != info->rate) { spa_log_warn(state->log, NAME" %p: Rate doesn't match (requested %iHz, get %iHz)", state, info->rate, rrate); - if (flags & SPA_NODE_PARAM_FLAG_NEAREST) - info->rate = rrate; - else + if (!SPA_FLAG_IS_SET(flags, SPA_NODE_PARAM_FLAG_NEAREST)) return -EINVAL; + info->rate = rrate; + match = false; } state->format = format; @@ -480,7 +481,7 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_ /* write the parameters to device */ CHECK(snd_pcm_hw_params(hndl, params), "set_hw_params"); - return 0; + return match ? 0 : 1; } static int set_swparams(struct state *state) diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 9f2454d16..84837cec5 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -639,7 +639,7 @@ static int port_set_format(void *object, port->have_format = false; } - if (spa_v4l2_set_format(this, &info, flags & SPA_NODE_PARAM_FLAG_TEST_ONLY) < 0) + if (spa_v4l2_set_format(this, &info, flags) < 0) return -EINVAL; if (!(flags & SPA_NODE_PARAM_FLAG_TEST_ONLY)) { diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index 252accb55..9e8c9d8e0 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -826,7 +826,7 @@ spa_v4l2_enum_format(struct impl *this, int seq, return res; } -static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, bool try_only) +static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, uint32_t flags) { struct port *port = &this->out_ports[0]; struct spa_v4l2_device *dev = &port->dev; @@ -837,6 +837,7 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, uint32_t video_format; struct spa_rectangle *size = NULL; struct spa_fraction *framerate = NULL; + bool match; spa_zero(fmt); spa_zero(streamparm); @@ -891,7 +892,7 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, if ((res = spa_v4l2_open(dev, this->props.device)) < 0) return res; - cmd = try_only ? VIDIOC_TRY_FMT : VIDIOC_S_FMT; + cmd = (flags & SPA_NODE_PARAM_FLAG_TEST_ONLY) ? VIDIOC_TRY_FMT : VIDIOC_S_FMT; if (xioctl(dev->fd, cmd, &fmt) < 0) { res = -errno; spa_log_error(this->log, "VIDIOC_S_FMT: %m"); @@ -902,9 +903,11 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, if (xioctl(dev->fd, VIDIOC_S_PARM, &streamparm) < 0) spa_log_warn(this->log, "VIDIOC_S_PARM: %m"); - if (reqfmt.fmt.pix.pixelformat != fmt.fmt.pix.pixelformat || - reqfmt.fmt.pix.width != fmt.fmt.pix.width || - reqfmt.fmt.pix.height != fmt.fmt.pix.height) { + match = (reqfmt.fmt.pix.pixelformat == fmt.fmt.pix.pixelformat && + reqfmt.fmt.pix.width == fmt.fmt.pix.width && + reqfmt.fmt.pix.height == fmt.fmt.pix.height); + + if (!match && !SPA_FLAG_IS_SET(flags, SPA_NODE_PARAM_FLAG_NEAREST)) { spa_log_error(this->log, "v4l2: wanted %.4s %dx%d, got %.4s %dx%d", (char *)&reqfmt.fmt.pix.pixelformat, reqfmt.fmt.pix.width, reqfmt.fmt.pix.height, @@ -913,14 +916,14 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, return -EINVAL; } + if (flags & SPA_NODE_PARAM_FLAG_TEST_ONLY) + return match ? 0 : 1; + spa_log_info(this->log, "v4l2: got %.4s %dx%d %d/%d", (char *)&fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height, streamparm.parm.capture.timeperframe.denominator, streamparm.parm.capture.timeperframe.numerator); - if (try_only) - return 0; - dev->have_format = true; size->width = fmt.fmt.pix.width; size->height = fmt.fmt.pix.height; @@ -935,7 +938,7 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, SPA_PORT_FLAG_TERMINAL; port->info.rate = SPA_FRACTION(port->rate.num, port->rate.denom); - return 0; + return match ? 0 : 1; } static int query_ext_ctrl_ioctl(struct port *port, struct v4l2_query_ext_ctrl *qctrl)