diff --git a/pipewire-jack/src/pipewire-jack.c b/pipewire-jack/src/pipewire-jack.c index a6584468b..23b043f30 100644 --- a/pipewire-jack/src/pipewire-jack.c +++ b/pipewire-jack/src/pipewire-jack.c @@ -195,9 +195,6 @@ struct port { struct spa_io_buffers io; struct spa_list mix; - bool have_format; - uint32_t rate; - bool zeroed; float *emptyptr; float empty[MAX_BUFFER_FRAMES + MAX_ALIGN]; @@ -1267,10 +1264,8 @@ static int param_enum_format(struct client *c, struct port *p, *param = spa_pod_builder_add_object(b, 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_Id(SPA_AUDIO_FORMAT_F32P), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(DEFAULT_SAMPLE_RATE, 1, INT32_MAX), - SPA_FORMAT_AUDIO_channels, SPA_POD_Int(1)); + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_DSP_F32)); break; case 1: *param = spa_pod_builder_add_object(b, @@ -1282,16 +1277,8 @@ static int param_enum_format(struct client *c, struct port *p, *param = spa_pod_builder_add_object(b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), - SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_RGBA_F32), - SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle( - &SPA_RECTANGLE(320, 240), - &SPA_RECTANGLE(1,1), - &SPA_RECTANGLE(INT32_MAX, INT32_MAX)), - SPA_FORMAT_VIDEO_framerate, SPA_POD_CHOICE_RANGE_Fraction( - &SPA_FRACTION(25,1), - &SPA_FRACTION(0,1), - &SPA_FRACTION(INT32_MAX,1))); + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_DSP_F32)); break; default: return -EINVAL; @@ -1302,48 +1289,26 @@ static int param_enum_format(struct client *c, struct port *p, static int param_format(struct client *c, struct port *p, struct spa_pod **param, struct spa_pod_builder *b) { - uint32_t channels[] = { SPA_AUDIO_CHANNEL_MONO }; - struct spa_pod_frame f; switch (p->object->port.type_id) { case 0: - spa_pod_builder_push_object(b, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format); - spa_pod_builder_add(b, - 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_Id(SPA_AUDIO_FORMAT_F32P), NULL); - if (p->have_format) { - spa_pod_builder_add(b, - SPA_FORMAT_AUDIO_rate, SPA_POD_Int(p->rate), NULL); - } else { - spa_pod_builder_add(b, - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(DEFAULT_SAMPLE_RATE, - 1, INT32_MAX), NULL); - } - spa_pod_builder_add(b, - SPA_FORMAT_AUDIO_channels, SPA_POD_Int(1), - SPA_FORMAT_AUDIO_position, SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, 1, channels), NULL); - *param = spa_pod_builder_pop(b, &f); + *param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_Format, SPA_PARAM_Format, + SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_DSP_F32)); break; case 1: *param = spa_pod_builder_add_object(b, - SPA_TYPE_OBJECT_Format, SPA_PARAM_Format, - SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application), - SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control)); + SPA_TYPE_OBJECT_Format, SPA_PARAM_Format, + SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application), + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control)); break; case 2: *param = spa_pod_builder_add_object(b, - SPA_TYPE_OBJECT_Format, SPA_PARAM_Format, - SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), - SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_RGBA_F32), - SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle( - &SPA_RECTANGLE(320, 240), - &SPA_RECTANGLE(1,1), - &SPA_RECTANGLE(INT32_MAX, INT32_MAX)), - SPA_FORMAT_VIDEO_framerate, SPA_POD_CHOICE_RANGE_Fraction( - &SPA_FRACTION(25,1), - &SPA_FRACTION(0,1), - &SPA_FRACTION(INT32_MAX,1))); + SPA_TYPE_OBJECT_Format, SPA_PARAM_Format, + SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_DSP_F32)); break; default: return -EINVAL; @@ -1407,7 +1372,6 @@ static int port_set_format(struct client *c, struct port *p, spa_list_for_each(mix, &p->mix, port_link) clear_buffers(c, mix); - p->have_format = false; } else { struct spa_audio_info info = { 0 }; @@ -1416,13 +1380,13 @@ static int port_set_format(struct client *c, struct port *p, switch (info.media_type) { case SPA_MEDIA_TYPE_audio: { - if (info.media_subtype != SPA_MEDIA_SUBTYPE_raw) + if (info.media_subtype != SPA_MEDIA_SUBTYPE_dsp) return -EINVAL; - if (spa_format_audio_raw_parse(param, &info.info.raw) < 0) + if (spa_format_audio_dsp_parse(param, &info.info.dsp) < 0) + return -EINVAL; + if (info.info.dsp.format != SPA_AUDIO_FORMAT_DSP_F32) return -EINVAL; - - p->rate = info.info.raw.rate; break; } case SPA_MEDIA_TYPE_application: @@ -1433,16 +1397,17 @@ static int port_set_format(struct client *c, struct port *p, { struct spa_video_info vinfo = { 0 }; - if (info.media_subtype != SPA_MEDIA_SUBTYPE_raw) + if (info.media_subtype != SPA_MEDIA_SUBTYPE_dsp) return -EINVAL; - if (spa_format_video_raw_parse(param, &vinfo.info.raw) < 0) + if (spa_format_video_dsp_parse(param, &vinfo.info.dsp) < 0) + return -EINVAL; + if (vinfo.info.dsp.format != SPA_VIDEO_FORMAT_DSP_F32) return -EINVAL; break; } default: return -EINVAL; } - p->have_format = true; } return 0; } diff --git a/spa/include/spa/param/audio/format-utils.h b/spa/include/spa/param/audio/format-utils.h index 4af8a249e..6b63e31a0 100644 --- a/spa/include/spa/param/audio/format-utils.h +++ b/spa/include/spa/param/audio/format-utils.h @@ -54,6 +54,16 @@ spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_r return res; } +static inline int +spa_format_audio_dsp_parse(const struct spa_pod *format, struct spa_audio_info_dsp *info) +{ + int res; + res = spa_pod_parse_object(format, + SPA_TYPE_OBJECT_Format, NULL, + SPA_FORMAT_AUDIO_format, SPA_POD_Id(&info->format)); + return res; +} + static inline struct spa_pod * spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, struct spa_audio_info_raw *info) { @@ -75,6 +85,18 @@ spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, struct return (struct spa_pod*)spa_pod_builder_pop(builder, &f); } +static inline struct spa_pod * +spa_format_audio_dsp_build(struct spa_pod_builder *builder, uint32_t id, struct spa_audio_info_dsp *info) +{ + struct spa_pod_frame f; + spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); + spa_pod_builder_add(builder, + SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_AUDIO_format, SPA_POD_Id(info->format), + 0); + return (struct spa_pod*)spa_pod_builder_pop(builder, &f); +} #ifdef __cplusplus } /* extern "C" */ diff --git a/spa/include/spa/param/audio/format.h b/spa/include/spa/param/audio/format.h index 30e054c6a..507a7453d 100644 --- a/spa/include/spa/param/audio/format.h +++ b/spa/include/spa/param/audio/format.h @@ -37,6 +37,7 @@ struct spa_audio_info { uint32_t media_subtype; union { struct spa_audio_info_raw raw; + struct spa_audio_info_dsp dsp; } info; }; diff --git a/spa/include/spa/param/audio/raw.h b/spa/include/spa/param/audio/raw.h index 3fff56ad6..44429f97e 100644 --- a/spa/include/spa/param/audio/raw.h +++ b/spa/include/spa/param/audio/raw.h @@ -82,8 +82,17 @@ enum spa_audio_format { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F64P, - SPA_AUDIO_FORMAT_START_Other = 0x300, + /* other formats start here */ + SPA_AUDIO_FORMAT_START_Other = 0x400, + /* Aliases */ + + /* DSP formats */ + SPA_AUDIO_FORMAT_DSP_S32 = SPA_AUDIO_FORMAT_S24_32P, + SPA_AUDIO_FORMAT_DSP_F32 = SPA_AUDIO_FORMAT_F32P, + SPA_AUDIO_FORMAT_DSP_F64 = SPA_AUDIO_FORMAT_F64P, + + /* native endian */ #if __BYTE_ORDER == __BIG_ENDIAN SPA_AUDIO_FORMAT_S16 = SPA_AUDIO_FORMAT_S16_BE, SPA_AUDIO_FORMAT_U16 = SPA_AUDIO_FORMAT_U16_BE, @@ -210,6 +219,11 @@ struct spa_audio_info_raw { #define SPA_KEY_AUDIO_CHANNEL "audio.channel" /**< an audio channel as string, * Ex. "FL" */ +struct spa_audio_info_dsp { + enum spa_audio_format format; /*< format, one of the DSP formats in enum spa_audio_format_dsp */ +}; + +#define SPA_AUDIO_INFO_DSP_INIT(...) (struct spa_audio_info_dsp) { __VA_ARGS__ } #ifdef __cplusplus } /* extern "C" */ diff --git a/spa/include/spa/param/video/format-utils.h b/spa/include/spa/param/video/format-utils.h index 7dea4f972..19964973b 100644 --- a/spa/include/spa/param/video/format-utils.h +++ b/spa/include/spa/param/video/format-utils.h @@ -57,6 +57,16 @@ spa_format_video_raw_parse(const struct spa_pod *format, SPA_FORMAT_VIDEO_colorPrimaries, SPA_POD_OPT_Id(&info->color_primaries)); } +static inline int +spa_format_video_dsp_parse(const struct spa_pod *format, + struct spa_video_info_dsp *info) +{ + return spa_pod_parse_object(format, + SPA_TYPE_OBJECT_Format, NULL, + SPA_FORMAT_VIDEO_format, SPA_POD_Id(&info->format), + SPA_FORMAT_VIDEO_modifier, SPA_POD_OPT_Long(&info->modifier)); +} + static inline struct spa_pod * spa_format_video_raw_build(struct spa_pod_builder *builder, uint32_t id, struct spa_video_info_raw *info) @@ -109,6 +119,23 @@ spa_format_video_raw_build(struct spa_pod_builder *builder, uint32_t id, return (struct spa_pod*)spa_pod_builder_pop(builder, &f); } +static inline struct spa_pod * +spa_format_video_dsp_build(struct spa_pod_builder *builder, uint32_t id, + struct spa_video_info_dsp *info) +{ + struct spa_pod_frame f; + spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); + spa_pod_builder_add(builder, + SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_VIDEO_format, SPA_POD_Id(info->format), + 0); + if (info->modifier) + spa_pod_builder_add(builder, + SPA_FORMAT_VIDEO_modifier, SPA_POD_Long(info->modifier), 0); + return (struct spa_pod*)spa_pod_builder_pop(builder, &f); +} + static inline int spa_format_video_h264_parse(const struct spa_pod *format, struct spa_video_info_h264 *info) diff --git a/spa/include/spa/param/video/format.h b/spa/include/spa/param/video/format.h index 0837b63fe..f1edb749f 100644 --- a/spa/include/spa/param/video/format.h +++ b/spa/include/spa/param/video/format.h @@ -37,6 +37,7 @@ struct spa_video_info { uint32_t media_subtype; union { struct spa_video_info_raw raw; + struct spa_video_info_dsp dsp; struct spa_video_info_h264 h264; struct spa_video_info_mjpg mjpg; } info; diff --git a/spa/include/spa/param/video/raw.h b/spa/include/spa/param/video/raw.h index 8868c4baa..eab65b8ec 100644 --- a/spa/include/spa/param/video/raw.h +++ b/spa/include/spa/param/video/raw.h @@ -120,6 +120,9 @@ enum spa_video_format { SPA_VIDEO_FORMAT_RGBA_F16, SPA_VIDEO_FORMAT_RGBA_F32, + + /* Aliases */ + SPA_VIDEO_FORMAT_DSP_F32 = SPA_VIDEO_FORMAT_RGBA_F32, }; /** @@ -204,6 +207,13 @@ struct spa_video_info_raw { #define SPA_VIDEO_INFO_RAW_INIT(...) (struct spa_video_info_raw) { __VA_ARGS__ } +struct spa_video_info_dsp { + enum spa_video_format format; + int64_t modifier; +}; + +#define SPA_VIDEO_INFO_DSP_INIT(...) (struct spa_video_info_dsp) { __VA_ARGS__ } + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/plugins/audioconvert/merger.c b/spa/plugins/audioconvert/merger.c index beb1d9232..3588a99a7 100644 --- a/spa/plugins/audioconvert/merger.c +++ b/spa/plugins/audioconvert/merger.c @@ -158,7 +158,7 @@ static void emit_port_info(struct impl *this, struct port *port, bool full) } static int init_port(struct impl *this, enum spa_direction direction, uint32_t port_id, - uint32_t rate, uint32_t position) + uint32_t position) { struct port *port = GET_PORT(this, direction, port_id); @@ -184,15 +184,12 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p port->n_buffers = 0; port->have_format = false; port->format.media_type = SPA_MEDIA_TYPE_audio; - port->format.media_subtype = SPA_MEDIA_SUBTYPE_raw; - port->format.info.raw.format = SPA_AUDIO_FORMAT_F32P; - port->format.info.raw.rate = rate; - port->format.info.raw.channels = 1; - port->format.info.raw.position[0] = position; + port->format.media_subtype = SPA_MEDIA_SUBTYPE_dsp; + port->format.info.dsp.format = SPA_AUDIO_FORMAT_DSP_F32; spa_list_init(&port->queue); - spa_log_debug(this->log, NAME " %p: add port %d:%d rate:%d position:%s", - this, direction, port_id, rate, port->position); + spa_log_debug(this->log, NAME " %p: add port %d:%d position:%s", + this, direction, port_id, port->position); emit_port_info(this, port, true); return 0; @@ -310,10 +307,9 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, this->port_count = info.info.raw.channels; this->monitor_count = this->monitor ? this->port_count : 0; for (i = 0; i < this->port_count; i++) { - init_port(this, SPA_DIRECTION_INPUT, i, info.info.raw.rate, - info.info.raw.position[i]); + init_port(this, SPA_DIRECTION_INPUT, i, info.info.raw.position[i]); if (this->monitor) - init_port(this, SPA_DIRECTION_OUTPUT, i+1, info.info.raw.rate, + init_port(this, SPA_DIRECTION_OUTPUT, i+1, info.info.raw.position[i]); } return 0; @@ -403,7 +399,10 @@ static int port_enum_formats(void *object, switch (index) { case 0: - if (PORT_IS_DSP(direction, port_id) || port->have_format) { + if (PORT_IS_DSP(direction, port_id)) { + *param = spa_format_audio_dsp_build(builder, + SPA_PARAM_EnumFormat, &port->format.info.dsp); + } else if (port->have_format) { *param = spa_format_audio_raw_build(builder, SPA_PARAM_EnumFormat, &port->format.info.raw); } @@ -481,7 +480,10 @@ impl_node_port_enum_params(void *object, int seq, if (result.index > 0) return 0; - param = spa_format_audio_raw_build(&b, id, &port->format.info.raw); + if (PORT_IS_DSP(direction, port_id)) + param = spa_format_audio_dsp_build(&b, id, &port->format.info.dsp); + else + param = spa_format_audio_raw_build(&b, id, &port->format.info.raw); break; case SPA_PARAM_Buffers: if (!port->have_format) @@ -557,7 +559,7 @@ static int setup_convert(struct impl *this) outport = GET_OUT_PORT(this, 0); - src_fmt = SPA_AUDIO_FORMAT_F32P; + src_fmt = SPA_AUDIO_FORMAT_DSP_F32; dst_fmt = outport->format.info.raw.format; spa_log_info(this->log, NAME " %p: %s/%d@%dx%d->%s/%d@%d", this, @@ -630,53 +632,52 @@ static int port_set_format(void *object, spa_log_error(this->log, "can't parse format %s", spa_strerror(res)); return res; } - - if (info.media_type != SPA_MEDIA_TYPE_audio || - info.media_subtype != SPA_MEDIA_SUBTYPE_raw) { - spa_log_error(this->log, "unexpected types %d/%d", - info.media_type, info.media_subtype); - return -EINVAL; - } - - if ((res = spa_format_audio_raw_parse(format, &info.info.raw)) < 0) { - spa_log_error(this->log, "can't parse format %s", spa_strerror(res)); - return res; - } - if (PORT_IS_DSP(direction, port_id)) { - if (info.info.raw.rate != port->format.info.raw.rate) { - spa_log_error(this->log, "unexpected rate %d<->%d", - info.info.raw.rate, port->format.info.raw.rate); + if (info.media_type != SPA_MEDIA_TYPE_audio || + info.media_subtype != SPA_MEDIA_SUBTYPE_dsp) { + spa_log_error(this->log, "unexpected types %d/%d", + info.media_type, info.media_subtype); return -EINVAL; } - if (info.info.raw.format != SPA_AUDIO_FORMAT_F32P) { + if ((res = spa_format_audio_dsp_parse(format, &info.info.dsp)) < 0) { + spa_log_error(this->log, "can't parse format %s", spa_strerror(res)); + return res; + } + if (info.info.dsp.format != SPA_AUDIO_FORMAT_DSP_F32) { spa_log_error(this->log, "unexpected format %d<->%d", - info.info.raw.format, SPA_AUDIO_FORMAT_F32P); - return -EINVAL; - } - if (info.info.raw.channels != 1) { - spa_log_error(this->log, "unexpected channels %d<->1", - info.info.raw.channels); + info.info.dsp.format, SPA_AUDIO_FORMAT_DSP_F32); return -EINVAL; } + port->blocks = 1; + port->stride = 4; } else { + if (info.media_type != SPA_MEDIA_TYPE_audio || + info.media_subtype != SPA_MEDIA_SUBTYPE_raw) { + spa_log_error(this->log, "unexpected types %d/%d", + info.media_type, info.media_subtype); + return -EINVAL; + } + if ((res = spa_format_audio_raw_parse(format, &info.info.raw)) < 0) { + spa_log_error(this->log, "can't parse format %s", spa_strerror(res)); + return res; + } if (info.info.raw.channels != this->port_count) { spa_log_error(this->log, "unexpected channels %d<->%d", info.info.raw.channels, this->port_count); return -EINVAL; } + port->stride = calc_width(&info); + if (SPA_AUDIO_FORMAT_IS_PLANAR(info.info.raw.format)) { + port->blocks = info.info.raw.channels; + } + else { + port->stride *= info.info.raw.channels; + port->blocks = 1; + } } - port->format = info; - port->stride = calc_width(&info); - if (SPA_AUDIO_FORMAT_IS_PLANAR(info.info.raw.format)) { - port->blocks = info.info.raw.channels; - } - else { - port->stride *= info.info.raw.channels; - port->blocks = 1; - } + spa_log_debug(this->log, NAME " %p: %d %d %d", this, port_id, port->stride, port->blocks); diff --git a/spa/plugins/audioconvert/splitter.c b/spa/plugins/audioconvert/splitter.c index e0c79556b..58ee49aef 100644 --- a/spa/plugins/audioconvert/splitter.c +++ b/spa/plugins/audioconvert/splitter.c @@ -145,7 +145,7 @@ static void emit_port_info(struct impl *this, struct port *port, bool full) } static int init_port(struct impl *this, enum spa_direction direction, - uint32_t port_id, uint32_t rate, uint32_t position) + uint32_t port_id, uint32_t position) { struct port *port = GET_OUT_PORT(this, port_id); @@ -178,14 +178,11 @@ static int init_port(struct impl *this, enum spa_direction direction, port->n_buffers = 0; port->have_format = false; port->format.media_type = SPA_MEDIA_TYPE_audio; - port->format.media_subtype = SPA_MEDIA_SUBTYPE_raw; - port->format.info.raw.format = SPA_AUDIO_FORMAT_F32P; - port->format.info.raw.rate = rate; - port->format.info.raw.channels = 1; - port->format.info.raw.position[0] = position; + port->format.media_subtype = SPA_MEDIA_SUBTYPE_dsp; + port->format.info.dsp.format = SPA_AUDIO_FORMAT_DSP_F32; - spa_log_debug(this->log, NAME " %p: init port %d:%d rate:%d position:%s", - this, direction, port_id, rate, port->position); + spa_log_debug(this->log, NAME " %p: init port %d:%d position:%s", + this, direction, port_id, port->position); emit_port_info(this, port, true); return 0; @@ -280,7 +277,8 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, if (port->have_format && memcmp(&port->format, &info, sizeof(info)) == 0) return 0; - spa_log_debug(this->log, NAME " %p: profile %d", this, info.info.raw.channels); + spa_log_debug(this->log, NAME " %p: port config %d/%d", this, + info.info.raw.rate, info.info.raw.channels); for (i = 0; i < this->port_count; i++) spa_node_emit_port_info(&this->hooks, @@ -293,7 +291,7 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, this->port_count = info.info.raw.channels; for (i = 0; i < this->port_count; i++) { - init_port(this, SPA_DIRECTION_OUTPUT, i, info.info.raw.rate, + init_port(this, SPA_DIRECTION_OUTPUT, i, info.info.raw.position[i]); } return 0; @@ -379,7 +377,10 @@ static int port_enum_formats(void *object, switch (index) { case 0: - if (direction == SPA_DIRECTION_OUTPUT || port->have_format) { + if (direction == SPA_DIRECTION_OUTPUT) { + *param = spa_format_audio_dsp_build(builder, + SPA_PARAM_EnumFormat, &port->format.info.dsp); + } else if (port->have_format) { *param = spa_format_audio_raw_build(builder, SPA_PARAM_EnumFormat, &port->format.info.raw); } @@ -462,7 +463,10 @@ impl_node_port_enum_params(void *object, int seq, if (result.index > 0) return 0; - param = spa_format_audio_raw_build(&b, id, &port->format.info.raw); + if (direction == SPA_DIRECTION_OUTPUT) + param = spa_format_audio_dsp_build(&b, id, &port->format.info.dsp); + else + param = spa_format_audio_raw_build(&b, id, &port->format.info.raw); break; case SPA_PARAM_Buffers: if (!port->have_format) @@ -540,7 +544,7 @@ static int setup_convert(struct impl *this) inport = GET_IN_PORT(this, 0); src_fmt = inport->format.info.raw.format; - dst_fmt = SPA_AUDIO_FORMAT_F32P; + dst_fmt = SPA_AUDIO_FORMAT_DSP_F32; spa_log_info(this->log, NAME " %p: %s/%d@%d->%s/%d@%dx%d", this, spa_debug_type_find_name(spa_type_audio_format, src_fmt), @@ -615,35 +619,38 @@ static int port_set_format(void *object, if ((res = spa_format_parse(format, &info.media_type, &info.media_subtype)) < 0) return res; - if (info.media_type != SPA_MEDIA_TYPE_audio || - info.media_subtype != SPA_MEDIA_SUBTYPE_raw) - return -EINVAL; - - if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) - return -EINVAL; - if (direction == SPA_DIRECTION_OUTPUT) { - if (info.info.raw.rate != port->format.info.raw.rate) + if (info.media_type != SPA_MEDIA_TYPE_audio || + info.media_subtype != SPA_MEDIA_SUBTYPE_dsp) return -EINVAL; - if (info.info.raw.format != SPA_AUDIO_FORMAT_F32P) + if (spa_format_audio_dsp_parse(format, &info.info.dsp) < 0) return -EINVAL; - if (info.info.raw.channels != 1) + if (info.info.dsp.format != SPA_AUDIO_FORMAT_DSP_F32) return -EINVAL; + + port->stride = 4; + port->blocks = 1; } else { + if (info.media_type != SPA_MEDIA_TYPE_audio || + info.media_subtype != SPA_MEDIA_SUBTYPE_raw) + return -EINVAL; + if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) + return -EINVAL; if (info.info.raw.channels != this->port_count) return -EINVAL; + + port->stride = calc_width(&info); + if (SPA_AUDIO_FORMAT_IS_PLANAR(info.info.raw.format)) { + port->blocks = info.info.raw.channels; + } else { + port->stride *= info.info.raw.channels; + port->blocks = 1; + } } port->format = info; - port->stride = calc_width(&info); - if (SPA_AUDIO_FORMAT_IS_PLANAR(info.info.raw.format)) { - port->blocks = info.info.raw.channels; - } else { - port->stride *= info.info.raw.channels; - port->blocks = 1; - } spa_log_debug(this->log, NAME " %p: %d %d %d", this, port_id, port->stride, port->blocks); if (direction == SPA_DIRECTION_INPUT) diff --git a/spa/plugins/audiomixer/mixer-dsp.c b/spa/plugins/audiomixer/mixer-dsp.c index a87e36960..b7d973ba1 100644 --- a/spa/plugins/audiomixer/mixer-dsp.c +++ b/spa/plugins/audiomixer/mixer-dsp.c @@ -315,16 +315,14 @@ static int port_enum_formats(void *object, switch (index) { case 0: if (this->have_format) { - *param = spa_format_audio_raw_build(builder, SPA_PARAM_EnumFormat, - &this->format.info.raw); + *param = spa_format_audio_dsp_build(builder, SPA_PARAM_EnumFormat, + &this->format.info.dsp); } else { *param = spa_pod_builder_add_object(builder, 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_Id(SPA_AUDIO_FORMAT_F32P), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(44100, 1, INT32_MAX), - SPA_FORMAT_AUDIO_channels, SPA_POD_Int(1)); + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_DSP_F32)); } break; default: @@ -373,7 +371,7 @@ next: if (result.index > 0) return 0; - param = spa_format_audio_raw_build(&b, id, &this->format.info.raw); + param = spa_format_audio_dsp_build(&b, id, &this->format.info.dsp); break; case SPA_PARAM_Buffers: @@ -495,23 +493,18 @@ static int port_set_format(void *object, return res; if (info.media_type != SPA_MEDIA_TYPE_audio || - info.media_subtype != SPA_MEDIA_SUBTYPE_raw) + info.media_subtype != SPA_MEDIA_SUBTYPE_dsp) return -EINVAL; - if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) + if (spa_format_audio_dsp_parse(format, &info.info.dsp) < 0) return -EINVAL; - if (info.info.raw.format != SPA_AUDIO_FORMAT_F32P) - return -EINVAL; - if (info.info.raw.channels != 1) + if (info.info.dsp.format != SPA_AUDIO_FORMAT_DSP_F32) return -EINVAL; - if (this->have_format) { - if (info.info.raw.rate != this->format.info.raw.rate) - return -EINVAL; - } else { - this->ops.fmt = info.info.raw.format; - this->ops.n_channels = info.info.raw.channels; + if (!this->have_format) { + this->ops.fmt = info.info.dsp.format; + this->ops.n_channels = 1; this->ops.cpu_flags = this->cpu_flags; if ((res = mix_ops_init(&this->ops)) < 0) diff --git a/spa/plugins/jack/jack-sink.c b/spa/plugins/jack/jack-sink.c index 4fa3de684..9d97112f1 100644 --- a/spa/plugins/jack/jack-sink.c +++ b/spa/plugins/jack/jack-sink.c @@ -146,8 +146,8 @@ static int impl_node_enum_params(void *object, int seq, case SPA_PARAM_Format: switch (result.index) { case 0: - param = spa_format_audio_raw_build(&b, - id, &this->current_format.info.raw); + param = spa_format_audio_dsp_build(&b, + id, &this->current_format.info.dsp); break; default: return 0; @@ -447,11 +447,8 @@ static int init_ports(struct impl *this) } this->n_in_ports = i; - this->current_format.info.raw = SPA_AUDIO_INFO_RAW_INIT( - .format = SPA_AUDIO_FORMAT_F32P, - .flags = SPA_AUDIO_FLAG_UNPOSITIONED, - .rate = jack_get_sample_rate(client), - .channels = this->n_in_ports); + this->current_format.info.dsp = SPA_AUDIO_INFO_DSP_INIT( + .format = SPA_AUDIO_FORMAT_DSP_F32); spa_jack_client_add_listener(this->client, &this->client_listener, @@ -499,10 +496,8 @@ static int port_enum_formats(struct impl *this, *param = spa_pod_builder_add_object(builder, 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_Id(SPA_AUDIO_FORMAT_F32P), - SPA_FORMAT_AUDIO_rate, SPA_POD_Int(this->client->frame_rate), - SPA_FORMAT_AUDIO_channels, SPA_POD_Int(1)); + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_DSP_F32)); break; default: return 0; @@ -552,7 +547,7 @@ impl_node_port_enum_params(void *object, int seq, if (result.index > 0) return 0; - param = spa_format_audio_raw_build(&b, id, &port->current_format.info.raw); + param = spa_format_audio_dsp_build(&b, id, &port->current_format.info.dsp); break; case SPA_PARAM_Buffers: @@ -627,17 +622,16 @@ static int port_set_format(struct impl *this, struct port *port, return res; if (info.media_type != SPA_MEDIA_TYPE_audio && - info.media_subtype != SPA_MEDIA_SUBTYPE_raw) + info.media_subtype != SPA_MEDIA_SUBTYPE_dsp) return -EINVAL; - if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) + if (spa_format_audio_dsp_parse(format, &info.info.dsp) < 0) return -EINVAL; - if (info.info.raw.format == SPA_AUDIO_FORMAT_F32P) - port->stride = 4; - else + if (info.info.dsp.format != SPA_AUDIO_FORMAT_DSP_F32) return -EINVAL; + port->stride = 4; port->current_format = info; port->have_format = true; } diff --git a/spa/plugins/jack/jack-source.c b/spa/plugins/jack/jack-source.c index 04b4b62d5..83af98dff 100644 --- a/spa/plugins/jack/jack-source.c +++ b/spa/plugins/jack/jack-source.c @@ -148,8 +148,8 @@ static int impl_node_enum_params(void *object, int seq, case SPA_PARAM_Format: switch (result.index) { case 0: - param = spa_format_audio_raw_build(&b, - id, &this->current_format.info.raw); + param = spa_format_audio_dsp_build(&b, + id, &this->current_format.info.dsp); break; default: return 0; @@ -446,11 +446,8 @@ static int init_ports(struct impl *this) } this->n_out_ports = i; - this->current_format.info.raw = SPA_AUDIO_INFO_RAW_INIT( - .format = SPA_AUDIO_FORMAT_F32P, - .flags = SPA_AUDIO_FLAG_UNPOSITIONED, - .rate = jack_get_sample_rate(client), - .channels = this->n_out_ports); + this->current_format.info.dsp = SPA_AUDIO_INFO_DSP_INIT( + .format = SPA_AUDIO_FORMAT_DSP_F32); spa_jack_client_add_listener(this->client, &this->client_listener, @@ -498,10 +495,8 @@ static int port_enum_formats(struct impl *this, *param = spa_pod_builder_add_object(builder, 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_Id(SPA_AUDIO_FORMAT_F32P), - SPA_FORMAT_AUDIO_rate, SPA_POD_Int(this->client->frame_rate), - SPA_FORMAT_AUDIO_channels, SPA_POD_Int(1)); + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_DSP_F32)); break; default: return 0; @@ -551,7 +546,7 @@ impl_node_port_enum_params(void *object, int seq, if (result.index > 0) return 0; - param = spa_format_audio_raw_build(&b, id, &port->current_format.info.raw); + param = spa_format_audio_dsp_build(&b, id, &port->current_format.info.dsp); break; case SPA_PARAM_Buffers: @@ -627,17 +622,16 @@ static int port_set_format(struct impl *this, struct port *port, return res; if (info.media_type != SPA_MEDIA_TYPE_audio && - info.media_subtype != SPA_MEDIA_SUBTYPE_raw) + info.media_subtype != SPA_MEDIA_SUBTYPE_dsp) return -EINVAL; - if (spa_format_audio_raw_parse(format, &info.info.raw) < 0) + if (spa_format_audio_dsp_parse(format, &info.info.dsp) < 0) return -EINVAL; - if (info.info.raw.format == SPA_AUDIO_FORMAT_F32P) - port->stride = 4; - else + if (info.info.dsp.format != SPA_AUDIO_FORMAT_DSP_F32) return -EINVAL; + port->stride = 4; port->current_format = info; port->have_format = true; } diff --git a/spa/plugins/vulkan/vulkan-compute-source.c b/spa/plugins/vulkan/vulkan-compute-source.c index cf44e323f..97498d00f 100644 --- a/spa/plugins/vulkan/vulkan-compute-source.c +++ b/spa/plugins/vulkan/vulkan-compute-source.c @@ -46,11 +46,13 @@ #define NAME "vulkan-compute-source" -#define FRAMES_TO_TIME(port,f) ((port->current_format.info.raw.framerate.denom * (f) * SPA_NSEC_PER_SEC) / \ - (port->current_format.info.raw.framerate.num)) +#define FRAMES_TO_TIME(this,f) ((this->position->video.framerate.denom * (f) * SPA_NSEC_PER_SEC) / \ + (this->position->video.framerate.num)) #define DEFAULT_LIVE true +#define MAX_HEIGHT 1024 + struct props { bool live; }; @@ -80,8 +82,6 @@ struct port { bool have_format; struct spa_video_info current_format; - size_t bpp; - int stride; struct buffer buffers[MAX_BUFFERS]; uint32_t n_buffers; @@ -98,6 +98,9 @@ struct impl { struct spa_loop *data_loop; struct spa_system *data_system; + struct spa_io_clock *clock; + struct spa_io_position *position; + uint64_t info_all; struct spa_node_info info; struct spa_param_info params[2]; @@ -193,7 +196,23 @@ static int impl_node_enum_params(void *object, int seq, static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size) { - return -ENOTSUP; + struct impl *this = object; + + spa_return_val_if_fail(this != NULL, -EINVAL); + + switch (id) { + case SPA_IO_Clock: + if (size > 0 && size < sizeof(struct spa_io_clock)) + return -EINVAL; + this->clock = data; + break; + case SPA_IO_Position: + this->position = data; + break; + default: + return -ENOENT; + } + return 0; } static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, @@ -300,7 +319,7 @@ static int make_buffer(struct impl *this) b->outbuf->datas[0].chunk->offset = 0; b->outbuf->datas[0].chunk->size = n_bytes; - b->outbuf->datas[0].chunk->stride = port->stride; + b->outbuf->datas[0].chunk->stride = this->position->video.stride; if (b->h) { b->h->seq = this->frame_count; @@ -315,7 +334,7 @@ static int make_buffer(struct impl *this) } next: this->frame_count++; - this->elapsed_time = FRAMES_TO_TIME(port, this->frame_count); + this->elapsed_time = FRAMES_TO_TIME(this, this->frame_count); set_timer(this, true); return res; @@ -507,16 +526,8 @@ static int port_enum_formats(void *object, *param = spa_pod_builder_add_object(builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), - SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_RGBA_F32), - SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle( - &SPA_RECTANGLE(320, 240), - &SPA_RECTANGLE(1, 1), - &SPA_RECTANGLE(INT32_MAX, INT32_MAX)), - SPA_FORMAT_VIDEO_framerate, SPA_POD_CHOICE_RANGE_Fraction( - &SPA_FRACTION(25,1), - &SPA_FRACTION(0, 1), - &SPA_FRACTION(INT32_MAX, 1))); + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_DSP_F32)); break; default: return 0; @@ -565,15 +576,15 @@ impl_node_port_enum_params(void *object, int seq, if (result.index > 0) return 0; - param = spa_format_video_raw_build(&b, id, &port->current_format.info.raw); + param = spa_format_video_dsp_build(&b, id, &port->current_format.info.dsp); break; case SPA_PARAM_Buffers: { - struct spa_video_info_raw *raw_info = &port->current_format.info.raw; - if (!port->have_format) return -EIO; + if (this->position == NULL) + return -EIO; if (result.index > 0) return 0; @@ -581,8 +592,8 @@ impl_node_port_enum_params(void *object, int seq, SPA_TYPE_OBJECT_ParamBuffers, id, SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1), - SPA_PARAM_BUFFERS_size, SPA_POD_Int(port->stride * raw_info->size.height), - SPA_PARAM_BUFFERS_stride, SPA_POD_Int(port->stride), + SPA_PARAM_BUFFERS_size, SPA_POD_Int(this->position->video.stride * MAX_HEIGHT), + SPA_PARAM_BUFFERS_stride, SPA_POD_Int(this->position->video.stride), SPA_PARAM_BUFFERS_align, SPA_POD_Int(16)); break; } @@ -645,19 +656,17 @@ static int port_set_format(struct impl *this, struct port *port, return res; if (info.media_type != SPA_MEDIA_TYPE_video && - info.media_subtype != SPA_MEDIA_SUBTYPE_raw) + info.media_subtype != SPA_MEDIA_SUBTYPE_dsp) return -EINVAL; - if (spa_format_video_raw_parse(format, &info.info.raw) < 0) + if (spa_format_video_dsp_parse(format, &info.info.dsp) < 0) return -EINVAL; - if (info.info.raw.format == SPA_VIDEO_FORMAT_RGBA_F32) - port->bpp = 16; - else + if (info.info.dsp.format != SPA_VIDEO_FORMAT_DSP_F32) return -EINVAL; - this->state.constants.width = info.info.raw.size.width; - this->state.constants.height = info.info.raw.size.height; + this->state.constants.width = this->position->video.size.width; + this->state.constants.height = this->position->video.size.height; port->current_format = info; port->have_format = true; @@ -666,8 +675,6 @@ static int port_set_format(struct impl *this, struct port *port, port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; if (port->have_format) { - struct spa_video_info_raw *raw_info = &port->current_format.info.raw; - port->stride = SPA_ROUND_UP_N(port->bpp * raw_info->size.width, 4); port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE); port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ); } else { diff --git a/src/daemon/pipewire.conf.in b/src/daemon/pipewire.conf.in index 00f383c0a..1a7c8d714 100644 --- a/src/daemon/pipewire.conf.in +++ b/src/daemon/pipewire.conf.in @@ -4,6 +4,15 @@ #set-prop context.data-loop.library.name.system support/libspa-support #set-prop link.max-buffers 64 +#set-prop default.clock.rate 48000 +#set-prop default.clock.quantum 1024 +#set-prop default.clock.min-quantum 32 +#set-prop default.clock.max-quantum 8192 +#set-prop default.video.width 320 +#set-prop default.video.height 240 +#set-prop default.video.rate.num 25 +#set-prop default.video.rate.denom 1 + add-spa-lib audio.convert* audioconvert/libspa-audioconvert add-spa-lib api.alsa.* alsa/libspa-alsa add-spa-lib api.v4l2.* v4l2/libspa-v4l2 diff --git a/src/examples/video-play.c b/src/examples/video-play.c index ac6678c75..682d12739 100644 --- a/src/examples/video-play.c +++ b/src/examples/video-play.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -34,7 +35,6 @@ #define WIDTH 640 #define HEIGHT 480 -#define BPP 3 #define MAX_BUFFERS 64 @@ -57,8 +57,11 @@ struct data { struct pw_stream *stream; struct spa_hook stream_listener; - struct spa_video_info_raw format; + struct spa_io_position *position; + + struct spa_video_info format; int32_t stride; + struct spa_rectangle size; int counter; SDL_Rect rect; @@ -177,10 +180,10 @@ on_process(void *_data) src = sdata; dst = ddata; - if (data->format.format == SPA_VIDEO_FORMAT_RGBA_F32) { - for (i = 0; i < data->format.size.height; i++) { + if (data->format.media_subtype == SPA_MEDIA_SUBTYPE_dsp) { + for (i = 0; i < data->size.height; i++) { struct pixel *p = (struct pixel *) src; - for (j = 0; j < data->format.size.width; j++) { + for (j = 0; j < data->size.width; j++) { dst[j * 4 + 0] = SPA_CLAMP(lrintf(p[j].r * 255.0f), 0, 255); dst[j * 4 + 1] = SPA_CLAMP(lrintf(p[j].g * 255.0f), 0, 255); dst[j * 4 + 2] = SPA_CLAMP(lrintf(p[j].b * 255.0f), 0, 255); @@ -191,7 +194,7 @@ on_process(void *_data) } } else { - for (i = 0; i < data->format.size.height; i++) { + for (i = 0; i < data->size.height; i++) { memcpy(dst, src, ostride); src += sstride; dst += dstride; @@ -229,6 +232,18 @@ static void on_stream_state_changed(void *_data, enum pw_stream_state old, } } +static void +on_stream_io_changed(void *_data, uint32_t id, void *area, uint32_t size) +{ + struct data *data = _data; + + switch (id) { + case SPA_IO_Position: + data->position = area; + break; + } +} + /* Be notified when the stream param changes. We're only looking at the * format changes. * @@ -258,13 +273,32 @@ on_stream_param_changed(void *_data, uint32_t id, const struct spa_pod *param) fprintf(stderr, "got format:\n"); spa_debug_format(2, NULL, param); - /* call a helper function to parse the format for us. */ - spa_format_video_raw_parse(param, &data->format); + if (spa_format_parse(param, &data->format.media_type, &data->format.media_subtype) < 0) + return; - if (data->format.format == SPA_VIDEO_FORMAT_RGBA_F32) + if (data->format.media_type != SPA_MEDIA_TYPE_video) + return; + + switch (data->format.media_subtype) { + case SPA_MEDIA_SUBTYPE_raw: + /* call a helper function to parse the format for us. */ + spa_format_video_raw_parse(param, &data->format.info.raw); + sdl_format = id_to_sdl_format(data->format.info.raw.format); + data->size = SPA_RECTANGLE(data->format.info.raw.size.width, + data->format.info.raw.size.height); + break; + case SPA_MEDIA_SUBTYPE_dsp: + spa_format_video_dsp_parse(param, &data->format.info.dsp); + if (data->format.info.dsp.format != SPA_VIDEO_FORMAT_DSP_F32) + return; sdl_format = SDL_PIXELFORMAT_RGBA32; - else - sdl_format = id_to_sdl_format(data->format.format); + data->size = SPA_RECTANGLE(data->position->video.size.width, + data->position->video.size.height); + break; + default: + sdl_format = SDL_PIXELFORMAT_UNKNOWN; + break; + } if (sdl_format == SDL_PIXELFORMAT_UNKNOWN) { pw_stream_set_error(stream, -EINVAL, "unknown pixel format"); @@ -274,15 +308,15 @@ on_stream_param_changed(void *_data, uint32_t id, const struct spa_pod *param) data->texture = SDL_CreateTexture(data->renderer, sdl_format, SDL_TEXTUREACCESS_STREAMING, - data->format.size.width, - data->format.size.height); + data->size.width, + data->size.height); SDL_LockTexture(data->texture, NULL, &d, &data->stride); SDL_UnlockTexture(data->texture); data->rect.x = 0; data->rect.y = 0; - data->rect.w = data->format.size.width; - data->rect.h = data->format.size.height; + data->rect.w = data->size.width; + data->rect.h = data->size.height; /* a SPA_TYPE_OBJECT_ParamBuffers object defines the acceptable size, * number, stride etc of the buffers */ @@ -290,7 +324,7 @@ on_stream_param_changed(void *_data, uint32_t id, const struct spa_pod *param) SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 2, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1), - SPA_PARAM_BUFFERS_size, SPA_POD_Int(data->stride * data->format.size.height), + SPA_PARAM_BUFFERS_size, SPA_POD_Int(data->stride * data->size.height), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(data->stride), SPA_PARAM_BUFFERS_align, SPA_POD_Int(16)); @@ -323,6 +357,7 @@ on_stream_param_changed(void *_data, uint32_t id, const struct spa_pod *param) static const struct pw_stream_events stream_events = { PW_VERSION_STREAM_EVENTS, .state_changed = on_stream_state_changed, + .io_changed = on_stream_io_changed, .param_changed = on_stream_param_changed, .process = on_process, }; @@ -334,18 +369,28 @@ static int build_format(struct data *data, struct spa_pod_builder *b, const stru SDL_GetRendererInfo(data->renderer, &info); params[0] = sdl_build_formats(&info, b); - fprintf(stderr, "supported formats:\n"); + fprintf(stderr, "supported SDL formats:\n"); spa_debug_format(2, NULL, params[0]); - return 0; + params[1] = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, + SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_DSP_F32)); + + fprintf(stderr, "supported DSP formats:\n"); + spa_debug_format(2, NULL, params[1]); + + return 2; } int main(int argc, char *argv[]) { struct data data = { 0, }; - const struct spa_pod *params[1]; + const struct spa_pod *params[2]; uint8_t buffer[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + int res, n_params; pw_init(&argc, &argv); @@ -390,19 +435,22 @@ int main(int argc, char *argv[]) /* build the extra parameters to connect with. To connect, we can provide * a list of supported formats. We use a builder that writes the param * object to the stack. */ - build_format(&data, &b, params); + n_params = build_format(&data, &b, params); /* now connect the stream, we need a direction (input/output), * an optional target node to connect to, some flags and parameters */ - pw_stream_connect(data.stream, + if ((res = pw_stream_connect(data.stream, PW_DIRECTION_INPUT, data.path ? (uint32_t)atoi(data.path) : SPA_ID_INVALID, PW_STREAM_FLAG_AUTOCONNECT | /* try to automatically connect this stream */ PW_STREAM_FLAG_INACTIVE | /* we will activate ourselves */ PW_STREAM_FLAG_EXCLUSIVE | /* require exclusive access */ PW_STREAM_FLAG_MAP_BUFFERS, /* mmap the buffer data for us */ - params, 1); /* extra parameters, see above */ + params, n_params)) /* extra parameters, see above */ < 0) { + fprintf(stderr, "can't connect: %s\n", spa_strerror(res)); + return -1; + } /* do things until we quit the mainloop */ pw_main_loop_run(data.loop); diff --git a/src/pipewire/context.c b/src/pipewire/context.c index cd351e525..194f17296 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -43,6 +43,16 @@ #define NAME "context" + +#define DEFAULT_CLOCK_RATE 48000u +#define DEFAULT_CLOCK_QUANTUM 1024u +#define DEFAULT_CLOCK_MIN_QUANTUM 32u +#define DEFAULT_CLOCK_MAX_QUANTUM 8192u +#define DEFAULT_VIDEO_WIDTH 640 +#define DEFAULT_VIDEO_HEIGHT 480 +#define DEFAULT_VIDEO_RATE_NUM 25u +#define DEFAULT_VIDEO_RATE_DENOM 1u + /** \cond */ struct impl { struct pw_context this; @@ -109,6 +119,29 @@ static void fill_properties(struct pw_context *context) pw_properties_set(properties, PW_KEY_CORE_NAME, context->core->info.name); } +static uint32_t get_default(struct pw_properties *properties, const char *name, uint32_t def) +{ + uint32_t val; + const char *str; + if ((str = pw_properties_get(properties, name)) != NULL) + val = atoi(str); + else + val = def; + return val; +} + +static void fill_defaults(struct pw_context *this) +{ + struct pw_properties *p = this->properties; + this->defaults.clock_rate = get_default(p, "default.clock.rate", DEFAULT_CLOCK_RATE); + this->defaults.clock_quantum = get_default(p, "default.clock.quantum", DEFAULT_CLOCK_QUANTUM); + this->defaults.clock_min_quantum = get_default(p, "default.clock.min-quantum", DEFAULT_CLOCK_MIN_QUANTUM); + this->defaults.clock_max_quantum = get_default(p, "default.clock.max-quantum", DEFAULT_CLOCK_MAX_QUANTUM); + this->defaults.video_size.width = get_default(p, "default.video.width", DEFAULT_VIDEO_WIDTH); + this->defaults.video_size.height = get_default(p, "default.video.height", DEFAULT_VIDEO_HEIGHT); + this->defaults.video_rate.num = get_default(p, "default.video.rate.num", DEFAULT_VIDEO_RATE_NUM); + this->defaults.video_rate.denom = get_default(p, "default.video.rate.denom", DEFAULT_VIDEO_RATE_DENOM); +} /** Create a new context object * @@ -154,6 +187,8 @@ struct pw_context *pw_context_new(struct pw_loop *main_loop, this->properties = properties; + fill_defaults(this); + pr = pw_properties_copy(properties); if ((str = pw_properties_get(pr, "context.data-loop." PW_KEY_LIBRARY_NAME_SYSTEM))) pw_properties_set(pr, PW_KEY_LIBRARY_NAME_SYSTEM, str); @@ -716,11 +751,13 @@ static int collect_nodes(struct pw_impl_node *driver) quantum = min_quantum; if (quantum == 0) - quantum = DEFAULT_QUANTUM; + quantum = driver->context->defaults.clock_quantum; /* for now, we try to limit the latency between min and default, We can * go to max but we should really only do this when in power save mode */ - driver->quantum_current = SPA_CLAMP(quantum, MIN_QUANTUM, DEFAULT_QUANTUM); + driver->quantum_current = SPA_CLAMP(quantum, + driver->context->defaults.clock_min_quantum, + driver->context->defaults.clock_quantum); return 0; } @@ -779,7 +816,8 @@ int pw_context_recalc_graph(struct pw_context *context) if (target != NULL) { if (n->quantum_size > 0 && n->quantum_size < target->quantum_current) - target->quantum_current = SPA_MAX(MIN_QUANTUM, n->quantum_size); + target->quantum_current = + SPA_MAX(context->defaults.clock_min_quantum, n->quantum_size); } pw_impl_node_set_driver(n, target); pw_impl_node_set_state(n, target && n->active ? diff --git a/src/pipewire/filter.c b/src/pipewire/filter.c index 6ebcc45db..4a4b2e0f4 100644 --- a/src/pipewire/filter.c +++ b/src/pipewire/filter.c @@ -1266,11 +1266,8 @@ static void add_audio_dsp_port_params(struct filter *impl, struct port *port) spa_pod_builder_add_object(&b, 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_Id(SPA_AUDIO_FORMAT_F32P), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int( - 48000, 1, INT32_MAX), - SPA_FORMAT_AUDIO_channels, SPA_POD_Int(1))); + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_DSP_F32))); spa_pod_builder_init(&b, buffer, sizeof(buffer)); add_param(impl, port, SPA_PARAM_Buffers, @@ -1297,16 +1294,8 @@ static void add_video_dsp_port_params(struct filter *impl, struct port *port) spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), - SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_RGBA_F32), - SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle( - &SPA_RECTANGLE(320, 240), - &SPA_RECTANGLE(1,1), - &SPA_RECTANGLE(INT32_MAX, INT32_MAX)), - SPA_FORMAT_VIDEO_framerate, SPA_POD_CHOICE_RANGE_Fraction( - &SPA_FRACTION(25,1), - &SPA_FRACTION(0,1), - &SPA_FRACTION(INT32_MAX,1)))); + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), + SPA_FORMAT_VIDEO_format, SPA_POD_Id(SPA_VIDEO_FORMAT_DSP_F32))); } SPA_EXPORT diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index 220f3e44e..335762101 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -908,12 +908,17 @@ static void reset_segment(struct spa_io_segment *seg) seg->rate = 1.0; } -static void reset_position(struct spa_io_position *pos) +static void reset_position(struct pw_impl_node *this, struct spa_io_position *pos) { uint32_t i; + struct defaults *def = &this->context->defaults; - pos->clock.rate = SPA_FRACTION(1, 48000); - pos->clock.duration = DEFAULT_QUANTUM; + pos->clock.rate = SPA_FRACTION(1, def->clock_rate); + pos->clock.duration = def->clock_quantum; + pos->video.flags = SPA_IO_VIDEO_SIZE_VALID; + pos->video.size = def->video_size; + pos->video.stride = pos->video.size.width * 16; + pos->video.framerate = def->video_rate; pos->offset = INT64_MIN; pos->n_segments = 1; @@ -1008,7 +1013,7 @@ struct pw_impl_node *pw_context_create_node(struct pw_context *context, this->rt.target.data = this; this->rt.driver_target.signal = process_node; - reset_position(&this->rt.activation->position); + reset_position(this, &this->rt.activation->position); this->rt.activation->sync_timeout = 5 * SPA_NSEC_PER_SEC; this->rt.activation->sync_left = 0; diff --git a/src/pipewire/impl-port.c b/src/pipewire/impl-port.c index 5913b99d5..1b45f9859 100644 --- a/src/pipewire/impl-port.c +++ b/src/pipewire/impl-port.c @@ -502,13 +502,13 @@ static int setup_mixer(struct pw_impl_port *port, const struct spa_pod *param) switch (media_type) { case SPA_MEDIA_TYPE_audio: switch (media_subtype) { - case SPA_MEDIA_SUBTYPE_raw: + case SPA_MEDIA_SUBTYPE_dsp: { - struct spa_audio_info_raw info; - if ((res = spa_format_audio_raw_parse(param, &info)) < 0) + struct spa_audio_info_dsp info; + if ((res = spa_format_audio_dsp_parse(param, &info)) < 0) return res; - if (info.format != SPA_AUDIO_FORMAT_F32P || info.channels != 1) + if (info.format != SPA_AUDIO_FORMAT_DSP_F32) return -ENOTSUP; fallback_lib = "audiomixer/libspa-audiomixer"; diff --git a/src/pipewire/private.h b/src/pipewire/private.h index cc1764e9e..aa9163e89 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -48,9 +48,14 @@ struct ucred { #define spa_debug pw_log_trace #endif -#define DEFAULT_QUANTUM 1024u -#define MIN_QUANTUM 32u -#define MAX_QUANTUM 8192u +struct defaults { + uint32_t clock_rate; + uint32_t clock_quantum; + uint32_t clock_min_quantum; + uint32_t clock_max_quantum; + struct spa_rectangle video_size; + struct spa_fraction video_rate; +}; #define MAX_PARAMS 32 @@ -228,6 +233,8 @@ struct pw_context { struct pw_properties *properties; /**< properties of the context */ + struct defaults defaults; /**< default parameters */ + struct pw_mempool *pool; /**< global memory pool */ struct pw_map globals; /**< map of globals */