diff --git a/spa/plugins/audioconvert/audioadapter.c b/spa/plugins/audioconvert/audioadapter.c index 4704c7e61..ea0343598 100644 --- a/spa/plugins/audioconvert/audioadapter.c +++ b/spa/plugins/audioconvert/audioadapter.c @@ -603,6 +603,10 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, return -EINVAL; if (spa_format_audio_raw_parse(param, &info.info.raw) < 0) return -EINVAL; + if (info.info.raw.format == 0 || + info.info.raw.rate == 0 || + info.info.raw.channels == 0) + return -EINVAL; this->follower_current_format = info; break; diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 0b52f0fd9..39033a09d 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -1072,7 +1072,10 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) return -EINVAL; - if (info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + if (info.info.raw.format == 0 || + info.info.raw.rate == 0 || + info.info.raw.channels == 0 || + info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) return -EINVAL; infop = &info; @@ -1951,9 +1954,13 @@ static int port_set_format(void *object, spa_log_error(this->log, "can't parse format %s", spa_strerror(res)); return res; } - if (info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) { - spa_log_error(this->log, "too many channels %d > %d", - info.info.raw.channels, SPA_AUDIO_MAX_CHANNELS); + if (info.info.raw.format == 0 || + info.info.raw.rate == 0 || + info.info.raw.channels == 0 || + info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) { + spa_log_error(this->log, "invalid format:%d rate:%d channels:%d", + info.info.raw.format, info.info.raw.rate, + info.info.raw.channels); return -EINVAL; } port->stride = calc_width(&info); diff --git a/spa/plugins/audioconvert/test-source.c b/spa/plugins/audioconvert/test-source.c index 55a65c5d5..b352323fd 100644 --- a/spa/plugins/audioconvert/test-source.c +++ b/spa/plugins/audioconvert/test-source.c @@ -535,8 +535,12 @@ static int calc_width(struct spa_audio_info *info) case SPA_AUDIO_FORMAT_S24: case SPA_AUDIO_FORMAT_S24_OE: return 3; - default: + case SPA_AUDIO_FORMAT_S32P: + case SPA_AUDIO_FORMAT_S32: + case SPA_AUDIO_FORMAT_S32_OE: return 4; + default: + return 0; } } @@ -571,6 +575,12 @@ static int port_set_format(void *object, return res; port->stride = calc_width(&info); + if (port->stride == 0) + return -EINVAL; + if (info.info.raw.rate == 0 || + info.info.raw.channels == 0) + return -EINVAL; + if (SPA_AUDIO_FORMAT_IS_PLANAR(info.info.raw.format)) { port->blocks = info.info.raw.channels; } diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index 6aba1a012..41e7e3f7e 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -566,6 +566,10 @@ static int port_set_format(void *object, if (memcmp(&info, &this->format, sizeof(struct spa_audio_info))) return -EINVAL; } else { + if (info.info.raw.format == 0 || + info.info.raw.channels == 0) + return -EINVAL; + this->ops.fmt = info.info.raw.format; this->ops.n_channels = info.info.raw.channels; this->ops.cpu_flags = this->cpu_flags; diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index ff58e6a2a..f009b9a29 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -743,6 +743,10 @@ port_set_format(struct impl *this, if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) return -EINVAL; + if (info.info.raw.rate == 0 || + info.info.raw.channels == 0) + return -EINVAL; + switch (info.info.raw.format) { case SPA_AUDIO_FORMAT_S16: idx = 0; diff --git a/spa/plugins/avb/avb-pcm.c b/spa/plugins/avb/avb-pcm.c index 0adc7e366..8fe9503a3 100644 --- a/spa/plugins/avb/avb-pcm.c +++ b/spa/plugins/avb/avb-pcm.c @@ -439,7 +439,7 @@ static int spa_format_to_aaf(uint32_t format) } } -static int frame_size(uint32_t format) +static int calc_frame_size(uint32_t format) { switch(format) { case SPA_AUDIO_FORMAT_F32_BE: @@ -647,7 +647,7 @@ static int setup_packet(struct state *state, struct spa_audio_info *fmt) SPA_AVBTP_PACKET_AAF_SET_FORMAT(pdu, spa_format_to_aaf(state->format)); SPA_AVBTP_PACKET_AAF_SET_NSR(pdu, spa_rate_to_aaf(state->rate)); SPA_AVBTP_PACKET_AAF_SET_CHAN_PER_FRAME(pdu, state->channels); - SPA_AVBTP_PACKET_AAF_SET_BIT_DEPTH(pdu, frame_size(state->format)*8); + SPA_AVBTP_PACKET_AAF_SET_BIT_DEPTH(pdu, calc_frame_size(state->format)*8); SPA_AVBTP_PACKET_AAF_SET_DATA_LEN(pdu, payload_size); SPA_AVBTP_PACKET_AAF_SET_SP(pdu, SPA_AVBTP_AAF_PCM_SP_NORMAL); } @@ -690,14 +690,22 @@ int spa_avb_clear_format(struct state *state) int spa_avb_set_format(struct state *state, struct spa_audio_info *fmt, uint32_t flags) { - int res; + int res, frame_size; struct props *p = &state->props; + frame_size = calc_frame_size(fmt->info.raw.format); + if (frame_size == 0) + return -EINVAL; + + if (fmt->info.raw.rate == 0 || + fmt->info.raw.channels == 0) + return -EINVAL; + state->format = fmt->info.raw.format; state->rate = fmt->info.raw.rate; state->channels = fmt->info.raw.channels; state->blocks = 1; - state->stride = state->channels * frame_size(state->format); + state->stride = state->channels * frame_size; if ((res = setup_socket(state)) < 0) return res; diff --git a/spa/plugins/bluez5/media-sink.c b/spa/plugins/bluez5/media-sink.c index 7b4a2c791..c6bcd2789 100644 --- a/spa/plugins/bluez5/media-sink.c +++ b/spa/plugins/bluez5/media-sink.c @@ -1344,6 +1344,11 @@ static int port_set_format(struct impl *this, struct port *port, if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) return -EINVAL; + if (info.info.raw.rate == 0 || + info.info.raw.channels == 0 || + info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + return -EINVAL; + port->frame_size = info.info.raw.channels; switch (info.info.raw.format) { case SPA_AUDIO_FORMAT_S16: diff --git a/spa/plugins/bluez5/media-source.c b/spa/plugins/bluez5/media-source.c index 7d183fd60..58ff14a52 100644 --- a/spa/plugins/bluez5/media-source.c +++ b/spa/plugins/bluez5/media-source.c @@ -1101,6 +1101,11 @@ static int port_set_format(struct impl *this, struct port *port, if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) return -EINVAL; + if (info.info.raw.rate == 0 || + info.info.raw.channels == 0 || + info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + return -EINVAL; + port->frame_size = info.info.raw.channels; switch (info.info.raw.format) { diff --git a/spa/plugins/bluez5/sco-sink.c b/spa/plugins/bluez5/sco-sink.c index 8958b1b87..f8db7eaf8 100644 --- a/spa/plugins/bluez5/sco-sink.c +++ b/spa/plugins/bluez5/sco-sink.c @@ -1106,6 +1106,11 @@ static int port_set_format(struct impl *this, struct port *port, if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) return -EINVAL; + if (info.info.raw.format != SPA_AUDIO_FORMAT_S16_LE || + info.info.raw.rate == 0 || + info.info.raw.channels != 1) + return -EINVAL; + port->frame_size = info.info.raw.channels * 2; port->current_format = info; port->have_format = true; diff --git a/spa/plugins/bluez5/sco-source.c b/spa/plugins/bluez5/sco-source.c index 8156bf00b..17855065f 100644 --- a/spa/plugins/bluez5/sco-source.c +++ b/spa/plugins/bluez5/sco-source.c @@ -1073,6 +1073,11 @@ static int port_set_format(struct impl *this, struct port *port, if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) return -EINVAL; + if (info.info.raw.format != SPA_AUDIO_FORMAT_S16_LE || + info.info.raw.rate == 0 || + info.info.raw.channels != 1) + return -EINVAL; + port->frame_size = info.info.raw.channels * 2; port->current_format = info; port->have_format = true; diff --git a/spa/plugins/support/null-audio-sink.c b/spa/plugins/support/null-audio-sink.c index 4c000f3eb..e42c3c1c8 100644 --- a/spa/plugins/support/null-audio-sink.c +++ b/spa/plugins/support/null-audio-sink.c @@ -610,6 +610,11 @@ port_set_format(struct impl *this, if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) return -EINVAL; + if (info.info.raw.rate == 0 || + info.info.raw.channels == 0 || + info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + return -EINVAL; + if (info.info.raw.format == SPA_AUDIO_FORMAT_F32) { port->bpf = 4 * info.info.raw.channels; port->blocks = 1; diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index a378f41ff..9a4def62e 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -925,7 +925,6 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, return -EINVAL; } - fmt.fmt.pix.pixelformat = info->fourcc; fmt.fmt.pix.field = V4L2_FIELD_ANY; fmt.fmt.pix.width = size->width; diff --git a/spa/plugins/videoconvert/videoadapter.c b/spa/plugins/videoconvert/videoadapter.c index c09417b41..5b7bae51b 100644 --- a/spa/plugins/videoconvert/videoadapter.c +++ b/spa/plugins/videoconvert/videoadapter.c @@ -599,8 +599,9 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, if ((res = spa_format_parse(param, &info.media_type, &info.media_subtype)) < 0) return res; if (info.media_type != SPA_MEDIA_TYPE_video || - info.media_subtype != SPA_MEDIA_SUBTYPE_raw) - return -EINVAL; + info.media_subtype != SPA_MEDIA_SUBTYPE_raw) + return -EINVAL; + if (spa_format_video_raw_parse(param, &info.info.raw) < 0) return -EINVAL; diff --git a/spa/plugins/videotestsrc/videotestsrc.c b/spa/plugins/videotestsrc/videotestsrc.c index 977429759..f2f42c060 100644 --- a/spa/plugins/videotestsrc/videotestsrc.c +++ b/spa/plugins/videotestsrc/videotestsrc.c @@ -643,6 +643,12 @@ static int port_set_format(struct impl *this, struct port *port, else return -EINVAL; + if (info.info.raw.size.width == 0 || + info.info.raw.size.height == 0 || + info.info.raw.framerate.num == 0 || + info.info.raw.framerate.denom == 0) + return -EINVAL; + port->current_format = info; port->have_format = true; } diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index fe6fcc4f4..08102a428 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -321,10 +321,9 @@ static int port_enum_formats(void *object, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(3, + SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(2, SPA_AUDIO_FORMAT_S16, - SPA_AUDIO_FORMAT_S16, - SPA_AUDIO_FORMAT_S32), + SPA_AUDIO_FORMAT_S16), SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int( DEFAULT_RATE, 1, INT32_MAX), SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int( @@ -472,6 +471,11 @@ static int port_set_format(void *object, if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) return -EINVAL; + if (info.info.raw.format != SPA_AUDIO_FORMAT_S16 || + info.info.raw.channels == 0 || + info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + return -EINVAL; + this->bpf = 2 * info.info.raw.channels; this->current_format = info; port->have_format = true; diff --git a/src/examples/export-sink.c b/src/examples/export-sink.c index 9e0985475..ee8a57c45 100644 --- a/src/examples/export-sink.c +++ b/src/examples/export-sink.c @@ -303,11 +303,10 @@ static int port_set_format(void *object, Uint32 sdl_format; void *dest; - d->info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS; if (format == NULL) { + spa_zero(d->format); SDL_DestroyTexture(d->texture); - d->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); - d->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); + d->texture = NULL; } else { spa_debug_format(0, NULL, format); @@ -316,6 +315,9 @@ static int port_set_format(void *object, sdl_format = id_to_sdl_format(d->format.format); if (sdl_format == SDL_PIXELFORMAT_UNKNOWN) return -EINVAL; + if (d->format.size.width == 0 || + d->format.size.height == 0) + return -EINVAL; d->texture = SDL_CreateTexture(d->renderer, sdl_format, @@ -325,9 +327,16 @@ static int port_set_format(void *object, SDL_LockTexture(d->texture, NULL, &dest, &d->stride); SDL_UnlockTexture(d->texture); + } + d->info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS; + if (format) { d->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE); d->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ); + } else { + d->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); + d->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); } + spa_node_emit_port_info(&d->hooks, direction, port_id, &d->info); d->info.change_mask = 0; diff --git a/src/examples/export-source.c b/src/examples/export-source.c index f84d01d92..22dfa1426 100644 --- a/src/examples/export-source.c +++ b/src/examples/export-source.c @@ -275,26 +275,31 @@ static int port_set_format(void *object, { struct data *d = object; - d->info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS; if (format == NULL) { - d->format.format = 0; - d->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); - d->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); - spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_OUTPUT, 0, &d->info); - return 0; + spa_zero(d->format); + } else { + spa_debug_format(0, NULL, format); + + if (spa_format_audio_raw_parse(format, &d->format) < 0) + return -EINVAL; + + if (d->format.format != SPA_AUDIO_FORMAT_S16 && + d->format.format != SPA_AUDIO_FORMAT_F32) + return -EINVAL; + if (d->format.rate == 0 || + d->format.channels == 0 || + d->format.channels > SPA_AUDIO_MAX_CHANNELS) + return -EINVAL; } - spa_debug_format(0, NULL, format); - - if (spa_format_audio_raw_parse(format, &d->format) < 0) - return -EINVAL; - - if (d->format.format != SPA_AUDIO_FORMAT_S16 && - d->format.format != SPA_AUDIO_FORMAT_F32) - return -EINVAL; - - d->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE); - d->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ); + d->info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS; + if (format) { + d->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE); + d->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ); + } else { + d->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); + d->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); + } spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_OUTPUT, 0, &d->info); return 0; diff --git a/src/examples/local-v4l2.c b/src/examples/local-v4l2.c index 0e466ba8d..5f7476727 100644 --- a/src/examples/local-v4l2.c +++ b/src/examples/local-v4l2.c @@ -207,28 +207,39 @@ static int port_set_format(void *object, enum spa_direction direction, uint32_t Uint32 sdl_format; void *dest; - if (format == NULL) - return 0; + if (format == NULL) { + spa_zero(d->format); + SDL_DestroyTexture(d->texture); + d->texture = NULL; + } else { + spa_debug_format(0, NULL, format); - spa_debug_format(0, NULL, format); + spa_format_video_raw_parse(format, &d->format); - spa_format_video_raw_parse(format, &d->format); + sdl_format = id_to_sdl_format(d->format.format); + if (sdl_format == SDL_PIXELFORMAT_UNKNOWN) + return -EINVAL; + if (d->format.size.width == 0 || + d->format.size.height == 0) + return -EINVAL; - sdl_format = id_to_sdl_format(d->format.format); - if (sdl_format == SDL_PIXELFORMAT_UNKNOWN) - return -EINVAL; - - d->texture = SDL_CreateTexture(d->renderer, - sdl_format, - SDL_TEXTUREACCESS_STREAMING, - d->format.size.width, - d->format.size.height); - SDL_LockTexture(d->texture, NULL, &dest, &d->stride); - SDL_UnlockTexture(d->texture); + d->texture = SDL_CreateTexture(d->renderer, + sdl_format, + SDL_TEXTUREACCESS_STREAMING, + d->format.size.width, + d->format.size.height); + SDL_LockTexture(d->texture, NULL, &dest, &d->stride); + SDL_UnlockTexture(d->texture); + } d->info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS; - d->params[1] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE); - d->params[2] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ); + if (format) { + d->params[1] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE); + d->params[2] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ); + } else { + d->params[1] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); + d->params[2] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); + } spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_INPUT, 0, &d->info); return 0; diff --git a/src/examples/video-play-fixate.c b/src/examples/video-play-fixate.c index 1badc3c39..021eb0df5 100644 --- a/src/examples/video-play-fixate.c +++ b/src/examples/video-play-fixate.c @@ -340,6 +340,10 @@ on_stream_param_changed(void *_data, uint32_t id, const struct spa_pod *param) pw_stream_set_error(stream, -EINVAL, "unknown pixel format"); return; } + if (data->size.width == 0 || data->size.height == 0) { + pw_stream_set_error(stream, -EINVAL, "invalid size"); + return; + } data->texture = SDL_CreateTexture(data->renderer, sdl_format, diff --git a/src/examples/video-play-pull.c b/src/examples/video-play-pull.c index 2b2c34660..807677962 100644 --- a/src/examples/video-play-pull.c +++ b/src/examples/video-play-pull.c @@ -388,6 +388,10 @@ on_stream_param_changed(void *_data, uint32_t id, const struct spa_pod *param) pw_stream_set_error(stream, -EINVAL, "unknown pixel format"); return; } + if (data->size.width == 0 || data->size.height == 0) { + pw_stream_set_error(stream, -EINVAL, "invalid size"); + return; + } data->texture = SDL_CreateTexture(data->renderer, sdl_format, diff --git a/src/examples/video-play-reneg.c b/src/examples/video-play-reneg.c index aa071850a..f37b66285 100644 --- a/src/examples/video-play-reneg.c +++ b/src/examples/video-play-reneg.c @@ -233,6 +233,10 @@ on_stream_param_changed(void *_data, uint32_t id, const struct spa_pod *param) pw_stream_set_error(stream, -EINVAL, "unknown pixel format"); return; } + if (data->size.width == 0 || data->size.height == 0) { + pw_stream_set_error(stream, -EINVAL, "invalid size"); + return; + } data->texture = SDL_CreateTexture(data->renderer, sdl_format, diff --git a/src/examples/video-play.c b/src/examples/video-play.c index 68589c902..61c3114f7 100644 --- a/src/examples/video-play.c +++ b/src/examples/video-play.c @@ -336,6 +336,10 @@ on_stream_param_changed(void *_data, uint32_t id, const struct spa_pod *param) pw_stream_set_error(stream, -EINVAL, "unknown pixel format"); return; } + if (data->size.width == 0 || data->size.height == 0) { + pw_stream_set_error(stream, -EINVAL, "invalid size"); + return; + } data->texture = SDL_CreateTexture(data->renderer, sdl_format, diff --git a/src/modules/module-filter-chain.c b/src/modules/module-filter-chain.c index 82af3cb85..a8f89e394 100644 --- a/src/modules/module-filter-chain.c +++ b/src/modules/module-filter-chain.c @@ -1011,14 +1011,15 @@ static void param_changed(void *data, uint32_t id, const struct spa_pod *param) } else { struct spa_audio_info_raw info; spa_zero(info); - spa_format_audio_raw_parse(param, &info); - impl->rate = info.rate; - res = graph_instantiate(graph); - if (res < 0) { - pw_stream_set_error(impl->capture, res, - "can't start graph: %s", - spa_strerror(res)); + if ((res = spa_format_audio_raw_parse(param, &info)) < 0) + goto error; + if (info.rate == 0) { + res = -EINVAL; + goto error; } + impl->rate = info.rate; + if ((res = graph_instantiate(graph)) < 0) + goto error; } break; case SPA_PARAM_Props: @@ -1029,6 +1030,11 @@ static void param_changed(void *data, uint32_t id, const struct spa_pod *param) param_latency_changed(impl, param); break; } + return; + +error: + pw_stream_set_error(impl->capture, res, "can't start graph: %s", + spa_strerror(res)); } static const struct pw_stream_events in_stream_events = { diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c index 39f53b399..505ff1c13 100644 --- a/src/modules/module-loopback.c +++ b/src/modules/module-loopback.c @@ -375,6 +375,10 @@ static void capture_param_changed(void *data, uint32_t id, const struct spa_pod return; if (spa_format_audio_raw_parse(param, &info) < 0) return; + if (info.rate == 0 || + info.channels == 0 || + info.channels > SPA_AUDIO_MAX_CHANNELS) + return; impl->capture_info = info; recalculate_buffer(impl);