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.
This commit is contained in:
Wim Taymans 2020-05-08 17:52:30 +02:00
parent 955e1a6a18
commit 1ca7713057
3 changed files with 21 additions and 17 deletions

View file

@ -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)

View file

@ -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)) {

View file

@ -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)