Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 48
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Wed Nov 27 09:05:48 UTC 2024 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 1.2.7 + +------------------------------------------------------------------- Thu Nov 7 09:26:42 UTC 2024 - Bjørn Lie <zaitor@opensuse.org> - Update to version 1.2.6
View file
pipewire-aptx.spec
Changed
@@ -8,7 +8,7 @@ %define minimum_version 1.2.0 Name: pipewire-aptx -Version: 1.2.6 +Version: 1.2.7 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
_service
Changed
@@ -2,6 +2,6 @@ <service name="download_url"> <param name="host">gitlab.freedesktop.org</param> <param name="protocol">https</param> - <param name="path">/pipewire/pipewire/-/archive/1.2.6/pipewire-1.2.6.tar.bz2</param> + <param name="path">/pipewire/pipewire/-/archive/1.2.7/pipewire-1.2.7.tar.bz2</param> </service> </services> \ No newline at end of file
View file
_service:download_url:pipewire-1.2.6.tar.bz2/NEWS -> _service:download_url:pipewire-1.2.7.tar.bz2/NEWS
Changed
@@ -1,3 +1,56 @@ +# PipeWire 1.2.7 (2024-11-26) + +This is a bugfix release that is API and ABI compatible with the previous +1.2.x and 1.0.x releases. + +## Highlights + - Backport support for lazy scheduling. + - Handle the case where processing would stop when an ALSA driver is + destroyed. + - Add support for v4l2loopback in the v4l2 plugin. + - Small bug fixes and improvements. + +## PipeWire + - Invalidate the proxy ID when removed. + - Backport support for lazy scheduling. + - Fix profiler stats for async nodes. + - Fix EARLY_PROCESS again in pw-stream. (#3480) + +## Modules + - Fix a crasher issue when nodes are created in the wrong order in + module-filter-chain. + - Fix unmap bug in lv2 uri tables. + - Add ratelimit to jack-tunnel xruns. + - Remove hardcoded limit in filter-chain sofa plugin. + - Handle the MTU size correctly in module-rtp and handle large MTUs. + (#4396) + - Fix JSON float parsing errors in equalizer module. (#4418) + +## SPA + - Fix crash in audiotestsrc when using spa-inspect (#4365). + - Improve JSON float infinity checks. + - Improve resampler performace a little. + - Make audioconvert only output when there is something to output. + - Fix regression in v4l2 port flags which would disable support for + EXPBUF. + - Handle the case where an ALSA driver is destroyed and the follower + becomes a driver. Processing would stop. (#4401) + - Add support for v4l2loopback in the v4l2 plugin. + +## Pulse-server + - Give a better error message when running out of fds. + - Ensure positive latency reporting. + +## GStreamer + - Fix memory leak in deviceprovider. + - Fix locking when emitting an error. + +## Tools + - Fix pw-dot link labels. + +Older versions: + + # PipeWire 1.2.6 (2024-10-23) This is a bugfix release that is API and ABI compatible with the previous @@ -40,9 +93,6 @@ ## Docs - Backport docs from master. -Older versions: - - # PipeWire 1.2.5 (2024-09-27) This is an important bugfix release that is API and ABI compatible with the
View file
_service:download_url:pipewire-1.2.6.tar.bz2/doc/dox/api/spa-pod.dox -> _service:download_url:pipewire-1.2.7.tar.bz2/doc/dox/api/spa-pod.dox
Changed
@@ -219,11 +219,11 @@ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), // audio/raw properties - SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id( + SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(4, // 4 values follow SPA_AUDIO_FORMAT_S16, // default SPA_AUDIO_FORMAT_S16, // alternative1 SPA_AUDIO_FORMAT_S32, // alternative2 - SPA_AUDIO_FORMAT_f32 // alternative3 + SPA_AUDIO_FORMAT_F32 // alternative3 ), SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int( 44100, // default @@ -383,9 +383,9 @@ To parse properties in an object: \code{.c} -uint32_t type, subtype, format, rate, channels; +uint32_t id, type, subtype, format, rate, channels; spa_pod_parser_get_object(&p, - SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, + SPA_TYPE_OBJECT_Format, &id, SPA_FORMAT_mediaType, SPA_POD_Id(&type), SPA_FORMAT_mediaSubtype, SPA_POD_Id(&subtype), SPA_FORMAT_AUDIO_format, SPA_POD_Id(&format), @@ -401,9 +401,9 @@ and when they are not present, the variables will not be changed. \code{.c} -uint32_t type, subtype, format, rate = 0, channels = 0; +uint32_t id, type, subtype, format, rate = 0, channels = 0; spa_pod_parser_get_object(&p, - SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, + SPA_TYPE_OBJECT_Format, &id, SPA_FORMAT_mediaType, SPA_POD_Id(&type), SPA_FORMAT_mediaSubtype, SPA_POD_Id(&subtype), SPA_FORMAT_AUDIO_format, SPA_POD_Id(&format), @@ -425,10 +425,10 @@ Here is an example of parsing the format values as a POD: \code{.c} -uint32_t type, subtype; +uint32_t id, type, subtype; struct spa_pod *format; spa_pod_parser_get_object(&p, - SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, + SPA_TYPE_OBJECT_Format, &id, SPA_FORMAT_mediaType, SPA_POD_Id(&type), SPA_FORMAT_mediaSubtype, SPA_POD_Id(&subtype), SPA_FORMAT_AUDIO_format, SPA_POD_Pod(&format)); @@ -483,21 +483,21 @@ 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( + SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(4, // 4 values follow SPA_AUDIO_FORMAT_S16, // default SPA_AUDIO_FORMAT_S16, // alternative1 SPA_AUDIO_FORMAT_S32, // alternative2 - SPA_AUDIO_FORMAT_f32 // alternative3 + SPA_AUDIO_FORMAT_F32 // alternative3 )); filter = 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_CHOICE_ENUM_Id( + SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(3, // 3 values follow SPA_AUDIO_FORMAT_S16, // default SPA_AUDIO_FORMAT_S16, // alternative1 - SPA_AUDIO_FORMAT_f64 // alternative2 + SPA_AUDIO_FORMAT_F64 // alternative2 )); struct spa_pod *result;
View file
_service:download_url:pipewire-1.2.6.tar.bz2/doc/dox/internals/scheduling.dox -> _service:download_url:pipewire-1.2.7.tar.bz2/doc/dox/internals/scheduling.dox
Changed
@@ -206,4 +206,143 @@ extra eventfd to signal the server that the graph completed. This is used by the server to generate the profiler info. +## Lazy scheduling + +Normally, a driver will wake up the graph and all the followers need to process +the data in sync. There are cases where: + + 1. the follower might not be ready to process the data + 2. the driver rate is not ideal, the follower rate is better + 3. the driver might not know when new data is available in the follower and + might wake up the graph too often. + +In these cases, the driver and follower roles need to be reversed and a mechanism +needs to be provided so that the follower can know when it is worth processing the +graph. + +For notifying when the graph is ready to be processed, (non driver) nodes can send +a RequestProcess event which will arrive as a RequestProcess command in the driver. +The driver can then decide to run the graph or not. + +When the graph is started or partially controlled by RequestProcess events and +commands we say we have lazy scheduling. The driver is not always scheduling according +to its own rhythm but also depending on the follower. + +We can't just enable lazy scheduling when no follower will emit RequestProcess events +or when no driver will listen for RequestProcess commands. Two new node properties are +defined: + + - node.supports-lazy = 0 | 1 | ... + + 0 means lazy scheduling as a driver is not supported + >1 means lazy scheduling as a driver is supported with increasing preference + + - node.supports-request + + 0 means request events as a follower are not supported + >1 means request events as a follower are supported with increasing preference + + We can only enable lazy scheduling when both the driver and (at least one) follower + has the node.supports-lazy and node.supports-request property respectively. + + Node can end up as a driver (is_driver()) and lazy scheduling can be enabled (is_lazy()), + which results in the following cases: + + driver producer + -> node.driver = true + -> is_driving() && !is_lazy() + -> calls trigger_process() to start the graph + + lazy producer + -> node.driver = true + -> node.supports-lazy = 1 + -> is_driving() && is_lazy() + -> listens for RequestProcess and calls trigger_process() to start the graph + + requesting producer + -> node.supports-request = 1 + -> !is_driving() && is_lazy() + -> emits RequestProcess to suggest starting the graph + + follower producer + -> !is_driving() && !is_lazy() + + + driver consumer + -> node.driver = true + -> is_driving() && !is_lazy() + -> calls trigger_process() to start the graph + + lazy consumer + -> node.driver = true + -> node.supports-lazy = 1 + -> is_driving() && is_lazy() + -> listens for RequestProcess and calls trigger_process() to start the graph + + requesting consumer + -> node.supports-request = 1 + -> !is_driving() && is_lazy() + -> emits RequestProcess to suggest starting the graph + + follower consumer + -> !is_driving() && !is_lazy() + + +Some use cases: + + 1. Screensharing - driver producer, follower consumer + - The producer starts the graph when a new frame is available. + - The consumer consumes the new frames. + -> throttles to the rate of the producer and idles when no frames + are available. + + producer + - node.driver = true + + consumer + - node.driver = false + + -> producer selected as driver, consumer is simple follower. + lazy scheduling inactive (no lazy driver or no request follower) + + + 2. headless server - requesting producer, (semi) lazy driver consumer + + - The producer emits RequestProcess when new frames are available. + - The consumer requests new frames from the producer according to its + refresh rate when there are RequestProcess commands. + -> this throttles the framerate to the consumer but idles when there is + no activity on the producer. + + producer + - node.driver = true + - node.supports-request = 1 + + consumer + - node.driver = true + - node.supports-lazy = 2 + + -> consumer is selected as driver (lazy > request) + lazy scheduling active (1 lazy driver and at least 1 request follower) + + + 3. frame encoder - lazy driver producer, requesting follower consumer + + - The consumer pulls a frame when it is ready to encode the next one. + - The producer produces the next frame on demand. + -> throttles the speed to the consumer without idle. + + producer + - node.driver = true + - node.supports-lazy = 1 + + consumer + - node.driver = true + - node.supports-request = 1 + + -> producer is selected as driver (lazy <= request) + lazy scheduling active (1 lazy driver and at least 1 request follower) + + + */
View file
_service:download_url:pipewire-1.2.6.tar.bz2/meson.build -> _service:download_url:pipewire-1.2.7.tar.bz2/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '1.2.6', + version : '1.2.7', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3',
View file
_service:download_url:pipewire-1.2.6.tar.bz2/pipewire-alsa/alsa-plugins/ctl_pipewire.c -> _service:download_url:pipewire-1.2.7.tar.bz2/pipewire-alsa/alsa-plugins/ctl_pipewire.c
Changed
@@ -555,7 +555,7 @@ param = spa_pod_builder_pop(&b, &f0); pw_log_debug("set device %d mute/volume for node %d", dg->id, g->id); - pw_device_set_param((struct pw_node*)dg->proxy, + pw_device_set_param((struct pw_device*)dg->proxy, SPA_PARAM_Route, 0, param); } else { if (!SPA_FLAG_IS_SET(g->permissions, PW_PERM_W | PW_PERM_X))
View file
_service:download_url:pipewire-1.2.6.tar.bz2/pipewire-jack/src/pipewire-jack.c -> _service:download_url:pipewire-1.2.7.tar.bz2/pipewire-jack/src/pipewire-jack.c
Changed
@@ -3859,7 +3859,7 @@ pw_proxy_add_listener(proxy, &c->metadata->proxy_listener, &metadata_proxy_events, c); - pw_metadata_add_listener(proxy, + pw_metadata_add_listener(c->metadata->proxy, &c->metadata->listener, &metadata_events, c); do_sync = true;
View file
_service:download_url:pipewire-1.2.6.tar.bz2/pipewire-v4l2/src/pipewire-v4l2.c -> _service:download_url:pipewire-1.2.7.tar.bz2/pipewire-v4l2/src/pipewire-v4l2.c
Changed
@@ -2326,7 +2326,7 @@ } param = spa_pod_builder_pop(&b, &f0); - pw_node_set_param(file->node->proxy, SPA_PARAM_Props, 0, param); + pw_node_set_param((struct pw_node*)file->node->proxy, SPA_PARAM_Props, 0, param); found = true; pw_log_info("ctrl 0x%08" PRIx32 " set ok", arg->id);
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/include/spa/node/io.h -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/include/spa/node/io.h
Changed
@@ -127,6 +127,7 @@ struct spa_io_clock { #define SPA_IO_CLOCK_FLAG_FREEWHEEL (1u<<0) /* graph is freewheeling */ #define SPA_IO_CLOCK_FLAG_XRUN_RECOVER (1u<<1) /* recovering from xrun */ +#define SPA_IO_CLOCK_FLAG_LAZY (1u<<2) /* lazy scheduling */ uint32_t flags; /**< Clock flags */ uint32_t id; /**< Unique clock id, set by host application */ char name64; /**< Clock name prefixed with API, set by node when it receives
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/include/spa/utils/json.h -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/include/spa/utils/json.h
Changed
@@ -457,10 +457,8 @@ static inline char *spa_json_format_float(char *str, int size, float val) { if (SPA_UNLIKELY(!isnormal(val))) { - if (val == INFINITY) - val = FLT_MAX; - else if (val == -INFINITY) - val = FLT_MIN; + if (isinf(val)) + val = signbit(val) ? FLT_MIN : FLT_MAX; else val = 0.0f; }
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/alsa/alsa-pcm-sink.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/alsa/alsa-pcm-sink.c
Changed
@@ -326,11 +326,13 @@ if (this->n_buffers == 0) return -EIO; + this->want_started = true; if ((res = spa_alsa_start(this)) < 0) return res; break; case SPA_NODE_COMMAND_Suspend: case SPA_NODE_COMMAND_Pause: + this->want_started = false; if ((res = spa_alsa_pause(this)) < 0) return res; break;
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/alsa/alsa-pcm-source.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/alsa/alsa-pcm-source.c
Changed
@@ -292,11 +292,13 @@ if (this->n_buffers == 0) return -EIO; + this->want_started = true; if ((res = spa_alsa_start(this)) < 0) return res; break; case SPA_NODE_COMMAND_Pause: case SPA_NODE_COMMAND_Suspend: + this->want_started = false; if ((res = spa_alsa_pause(this)) < 0) return res; break;
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/alsa/alsa-pcm.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -828,6 +828,7 @@ char card_name256; snprintf(card_name, sizeof(card_name), "hw:%d", state->card_index); + spa_log_debug(state->log, "Trying to open ctl device '%s'", card_name); err = snd_ctl_open(&state->ctl, card_name, SND_CTL_NONBLOCK); if (err < 0) { @@ -894,6 +895,8 @@ state->multi_rate = true; state->htimestamp = false; state->htimestamp_max_errors = MAX_HTIMESTAMP_ERROR; + state->card_index = SPA_ID_INVALID; + for (i = 0; info && i < info->n_items; i++) { const char *k = info->itemsi.key; const char *s = info->itemsi.value; @@ -930,6 +933,17 @@ alsa_set_param(state, k, s); } } + + if (state->card_index == SPA_ID_INVALID) { + /* If we don't have a card index, see if we have a *:<idx> string */ + sscanf(state->props.device, "%*^::%u", &state->card_index); + if (state->card_index == SPA_ID_INVALID) { + spa_log_error(state->log, "Could not determine card index, maybe set %s", + SPA_KEY_API_ALSA_CARD); + return -EINVAL; + } + } + if (state->clock_name0 == '\0') snprintf(state->clock_name, sizeof(state->clock_name), "api.alsa.%s-%u", @@ -2481,7 +2495,6 @@ reset_buffers(state); state->alsa_sync = true; state->alsa_sync_warning = false; - state->alsa_recovering = false; state->alsa_started = false; return 0; @@ -2622,8 +2635,6 @@ } avail = state->threshold * 2; } - } else { - state->alsa_recovering = false; } *delay = avail; @@ -3508,9 +3519,8 @@ rt->driver = state->driver; spa_log_debug(state->log, "state:%p -> driver:%p", state, state->driver); - if(state->linked && state->matching) { + if(state->linked && state->matching) try_unlink(state); - } } if (state->following) { remove_sources(state); @@ -3682,6 +3692,8 @@ setup_matching(state); if (state->started) spa_loop_invoke(state->data_loop, do_state_sync, 0, NULL, 0, true, state); + else if (state->want_started) + spa_alsa_start(state); freewheel = pos != NULL && SPA_FLAG_IS_SET(pos->clock.flags, SPA_IO_CLOCK_FLAG_FREEWHEEL); if (state->freewheel != freewheel) {
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/alsa/alsa-pcm.h -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/alsa/alsa-pcm.h
Changed
@@ -133,6 +133,7 @@ unsigned int opened:1; unsigned int prepared:1; unsigned int started:1; + unsigned int want_started:1; snd_pcm_t *hndl; bool have_format; @@ -211,7 +212,6 @@ unsigned int alsa_started:1; unsigned int alsa_sync:1; unsigned int alsa_sync_warning:1; - unsigned int alsa_recovering:1; unsigned int following:1; unsigned int matching:1; unsigned int resample:1;
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/audioconvert/audioconvert.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -3272,7 +3272,7 @@ } dir = &this->dirSPA_DIRECTION_OUTPUT; - if (SPA_LIKELY(n_samples > 0 && (this->out_offset >= max_out || flush_out))) { + if (SPA_LIKELY(this->out_offset > 0 && (this->out_offset >= max_out || flush_out))) { /* queue output buffers */ for (i = 0; i < dir->n_ports; i++) { port = GET_OUT_PORT(this, i);
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/audioconvert/resample-native-impl.h -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/audioconvert/resample-native-impl.h
Changed
@@ -52,16 +52,13 @@ { \ struct native_data *data = r->data; \ uint32_t index, n_taps = data->n_taps, n_taps2 = n_taps/2; \ - uint32_t c, olen = *out_len, ilen = *in_len; \ - \ - if (r->channels == 0) \ - return; \ + uint32_t c, olen = *out_len, ilen = *in_len, ch = r->channels; \ \ index = ioffs; \ if (ooffs < olen && index + n_taps <= ilen) { \ uint32_t to_copy = SPA_MIN(olen - ooffs, \ ilen - (index + n_taps) + 1); \ - for (c = 0; c < r->channels; c++) { \ + for (c = 0; c < ch; c++) { \ const float *s = srcc; \ float *d = dstc; \ spa_memcpy(&dooffs, &sindex + n_taps2, \ @@ -74,12 +71,12 @@ *out_len = ooffs; \ } -#define INC(index,phase,n_phases) \ - index += inc; \ - phase += frac; \ - if (phase >= n_phases) { \ - phase -= n_phases; \ - index += 1; \ +#define INC(index,phase,n_phases) \ + index += inc; \ + phase += frac; \ + if (phase >= n_phases) { \ + phase -= n_phases; \ + index += 1; \ } #define MAKE_RESAMPLER_FULL(arch) \ @@ -89,24 +86,19 @@ uint32_t n_taps = data->n_taps, stride = data->filter_stride_os; \ uint32_t index, phase, n_phases = data->out_rate; \ uint32_t c, o, olen = *out_len, ilen = *in_len; \ - uint32_t inc = data->inc, frac = data->frac; \ - \ - if (r->channels == 0) \ - return; \ - \ - for (c = 0; c < r->channels; c++) { \ - const float *s = srcc; \ - float *d = dstc; \ - \ - index = ioffs; \ - phase = (uint32_t)data->phase; \ + uint32_t inc = data->inc, frac = data->frac, ch = r->channels; \ \ - for (o = ooffs; o < olen && index + n_taps <= ilen; o++) { \ + index = ioffs; \ + phase = (uint32_t)data->phase; \ + for (o = ooffs; o < olen && index + n_taps <= ilen; o++) { \ + float *filter = &data->filterphase * stride; \ + for (c = 0; c < ch; c++) { \ + const float *s = srcc; \ + float *d = dstc; \ inner_product_##arch(&do, &sindex, \ - &data->filterphase * stride, \ - n_taps); \ - INC(index, phase, n_phases); \ + filter, n_taps); \ } \ + INC(index, phase, n_phases); \ } \ *in_len = index; \ *out_len = o; \ @@ -121,28 +113,24 @@ uint32_t n_phases = data->n_phases, out_rate = data->out_rate; \ uint32_t n_taps = data->n_taps; \ uint32_t c, o, olen = *out_len, ilen = *in_len; \ - uint32_t inc = data->inc, frac = data->frac; \ + uint32_t inc = data->inc, frac = data->frac, ch = r->channels; \ float phase; \ \ - if (r->channels == 0) \ - return; \ - \ - for (c = 0; c < r->channels; c++) { \ - const float *s = srcc; \ - float *d = dstc; \ - \ - index = ioffs; \ - phase = data->phase; \ - \ - for (o = ooffs; o < olen && index + n_taps <= ilen; o++) { \ - float ph = phase * n_phases / out_rate; \ - uint32_t offset = (uint32_t)floorf(ph); \ + index = ioffs; \ + phase = data->phase; \ + for (o = ooffs; o < olen && index + n_taps <= ilen; o++) { \ + float ph = phase * n_phases / out_rate; \ + uint32_t offset = (uint32_t)floorf(ph); \ + float *filter0 = &data->filter(offset+0) * stride; \ + float *filter1 = &data->filter(offset+1) * stride; \ + float pho = ph - offset; \ + for (c = 0; c < ch; c++) { \ + const float *s = srcc; \ + float *d = dstc; \ inner_product_ip_##arch(&do, &sindex, \ - &data->filter(offset + 0) * stride, \ - &data->filter(offset + 1) * stride, \ - ph - offset, n_taps); \ - INC(index, phase, out_rate); \ + filter0, filter1, pho, n_taps); \ } \ + INC(index, phase, out_rate); \ } \ *in_len = index; \ *out_len = o; \
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/audiotestsrc/audiotestsrc.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/audiotestsrc/audiotestsrc.c
Changed
@@ -1046,8 +1046,18 @@ this = (struct impl *) handle; this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); + this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop); + if (this->data_loop == NULL) { + spa_log_error(this->log, "%p: could not find a data loop", this); + return -EINVAL; + } + this->data_system = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataSystem); + if (this->data_system == NULL) { + spa_log_error(this->log, "%p: could not find a data system", this); + return -EINVAL; + } for (i = 0; info && i < info->n_items; i++) { const char *k = info->itemsi.key;
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/v4l2/v4l2-source.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/v4l2/v4l2-source.c
Changed
@@ -58,6 +58,7 @@ struct spa_meta_videotransform *vt; struct v4l2_buffer v4l2_buffer; void *ptr; + void *mmap_ptr; }; #define MAX_CONTROLS 64 @@ -75,6 +76,8 @@ bool alloc_buffers; bool probed_expbuf; bool have_expbuf; + bool first_buffer; + uint32_t max_buffers; bool next_fmtdesc; struct v4l2_fmtdesc fmtdesc; @@ -578,10 +581,13 @@ return -EIO; if (result.index > 0) return 0; + if (port->max_buffers == 0) + return -EIO; param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamBuffers, id, - SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(4, 1, MAX_BUFFERS), + SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(SPA_MIN(4u, port->max_buffers), + 1, port->max_buffers), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1), SPA_PARAM_BUFFERS_size, SPA_POD_Int(port->fmt.fmt.pix.sizeimage), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(port->fmt.fmt.pix.bytesperline));
View file
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/v4l2/v4l2-utils.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/v4l2/v4l2-utils.c
Changed
@@ -120,7 +120,6 @@ spa_log_error(this->log, "'%s' VIDIOC_QBUF: %m", this->props.device); return -err; } - return 0; } @@ -147,6 +146,8 @@ if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_MAPPED)) { munmap(b->ptr, d0.maxsize); } + if (b->mmap_ptr) + munmap(b->mmap_ptr, b->v4l2_buffer.length); if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_ALLOCATED)) { spa_log_debug(this->log, "close %d", (int) d0.fd); close(d0.fd); @@ -911,12 +912,13 @@ spa_zero(reqbuf); reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuf.memory = V4L2_MEMORY_MMAP; - reqbuf.count = 2; + reqbuf.count = port->max_buffers = MAX_BUFFERS; if (xioctl(dev->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { spa_log_error(this->log, "'%s' VIDIOC_REQBUFS: %m", this->props.device); return -errno; } + port->max_buffers = reqbuf.count; spa_zero(expbuf); expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1048,6 +1050,8 @@ size->width = fmt.fmt.pix.width; size->height = fmt.fmt.pix.height; + probe_expbuf(this); + port->fmt = fmt; port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS | SPA_PORT_CHANGE_MASK_RATE; port->info.flags = (port->alloc_buffers ? SPA_PORT_FLAG_CAN_ALLOC_BUFFERS : 0) | @@ -1057,8 +1061,6 @@ port->info.rate.num = streamparm.parm.capture.timeperframe.numerator; port->info.rate.denom = streamparm.parm.capture.timeperframe.denominator; - probe_expbuf(this); - return match ? 0 : 1; } @@ -1406,15 +1408,18 @@ if (xioctl(dev->fd, VIDIOC_DQBUF, &buf) < 0) return -errno; + spa_log_trace(this->log, "v4l2 %p: have output %d/%d", this, buf.index, buf.sequence); + /* Drop the first frame in order to work around common firmware * timestamp issues */ - if (buf.sequence == 0) { - xioctl(dev->fd, VIDIOC_QBUF, &buf); + if (port->first_buffer) { + port->first_buffer = false; + if (xioctl(dev->fd, VIDIOC_QBUF, &buf) < 0) + spa_log_warn(this->log, "v4l2 %p: error qbuf: %m", this); return 0; } pts = SPA_TIMEVAL_TO_NSEC(&buf.timestamp); - spa_log_trace(this->log, "v4l2 %p: have output %d", this, buf.index); if (this->clock) { /* FIXME, we should follow the driver clock and target_ values. @@ -1447,12 +1452,15 @@ d = b->outbuf->datas; d0.chunk->offset = 0; - d0.chunk->size = buf.bytesused; + d0.chunk->size = SPA_MIN(buf.bytesused, d0.maxsize); d0.chunk->stride = port->fmt.fmt.pix.bytesperline; d0.chunk->flags = 0; if (buf.flags & V4L2_BUF_FLAG_ERROR) d0.chunk->flags |= SPA_CHUNK_FLAG_CORRUPTED; + if (b->mmap_ptr && b->ptr) + memcpy(b->ptr, b->mmap_ptr, d0.chunk->size); + spa_list_append(&port->queue, &b->link); return 0; } @@ -1463,6 +1471,7 @@ struct spa_io_buffers *io; struct port *port = &this->out_ports0; struct buffer *b; + int res; if (source->rmask & SPA_IO_ERR) { struct port *port = &this->out_ports0; @@ -1477,8 +1486,10 @@ return; } - if (mmap_read(this) < 0) + if ((res = mmap_read(this)) < 0) { + spa_log_warn(this->log, "v4l2 %p: mmap read error:%s", this, spa_strerror(res)); return; + } if (spa_list_is_empty(&port->queue)) return; @@ -1534,8 +1545,22 @@ reqbuf.count = n_buffers; if (xioctl(dev->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { - spa_log_error(this->log, "'%s' VIDIOC_REQBUFS %m", this->props.device); - return -errno; + if (port->memtype != V4L2_MEMORY_USERPTR) { + spa_log_error(this->log, "'%s' VIDIOC_REQBUFS %m", this->props.device); + return -errno; + } + /* some drivers (v4l2loopback) don't support USERPTR + * and so we need to try again with MMAP and memcpy */ + port->memtype = V4L2_MEMORY_MMAP; + spa_zero(reqbuf); + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = port->memtype; + reqbuf.count = n_buffers; + + if (xioctl(dev->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + spa_log_error(this->log, "'%s' VIDIOC_REQBUFS %m", this->props.device); + return -errno; + } } spa_log_debug(this->log, "got %d buffers", reqbuf.count); if (reqbuf.count < n_buffers) { @@ -1568,7 +1593,8 @@ b->v4l2_buffer.memory = port->memtype; b->v4l2_buffer.index = i; - if (port->memtype == V4L2_MEMORY_USERPTR) { + if (port->memtype == V4L2_MEMORY_USERPTR || + port->memtype == V4L2_MEMORY_MMAP) { if (d0.data == NULL) { void *data; @@ -1586,8 +1612,24 @@ else b->ptr = d0.data; - b->v4l2_buffer.m.userptr = (unsigned long) b->ptr; - b->v4l2_buffer.length = d0.maxsize; + if (port->memtype == V4L2_MEMORY_USERPTR) { + b->v4l2_buffer.m.userptr = (unsigned long) b->ptr; + b->v4l2_buffer.length = d0.maxsize; + } + else { + if (xioctl(dev->fd, VIDIOC_QUERYBUF, &b->v4l2_buffer) < 0) { + spa_log_error(this->log, "'%s' VIDIOC_QUERYBUF: %m", this->props.device); + return -errno; + } + b->mmap_ptr = mmap(NULL, + b->v4l2_buffer.length, + PROT_READ, MAP_PRIVATE, + dev->fd, b->v4l2_buffer.m.offset); + if (b->mmap_ptr == MAP_FAILED) { + spa_log_error(this->log, "'%s' mmap: %m", this->props.device); + return -errno; + } + } } else if (port->memtype == V4L2_MEMORY_DMABUF) { b->v4l2_buffer.m.fd = d0.fd; @@ -1798,6 +1840,9 @@ spa_log_debug(this->log, "starting"); + port->first_buffer = true; + mmap_read(this); + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl(dev->fd, VIDIOC_STREAMON, &type) < 0) { spa_log_error(this->log, "'%s' VIDIOC_STREAMON: %m", this->props.device);
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/examples/video-play-pull.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/examples/video-play-pull.c
Changed
@@ -259,7 +259,11 @@ enable_timeouts(data, false); break; case PW_STREAM_STATE_STREAMING: - enable_timeouts(data, true); + printf("driving:%d lazy:%d\n", + pw_stream_is_driving(data->stream), + pw_stream_is_lazy(data->stream)); + if (pw_stream_is_driving(data->stream) != pw_stream_is_lazy(data->stream)) + enable_timeouts(data, true); break; default: break; @@ -288,8 +292,7 @@ static void on_timeout(void *userdata, uint64_t expirations) { struct data *data = userdata; - if (!data->have_request_process) - pw_stream_trigger_process(data->stream); + pw_stream_trigger_process(data->stream); } static void @@ -298,8 +301,7 @@ struct data *data = _data; switch (SPA_NODE_COMMAND_ID(command)) { case SPA_NODE_COMMAND_RequestProcess: - data->have_request_process = true; - enable_timeouts(data, false); + pw_log_trace("%p trigger", data); pw_stream_trigger_process(data->stream); break; default: @@ -507,7 +509,8 @@ props = pw_properties_new(PW_KEY_MEDIA_TYPE, "Video", PW_KEY_MEDIA_CATEGORY, "Capture", PW_KEY_MEDIA_ROLE, "Camera", - PW_KEY_PRIORITY_DRIVER, "10000", + PW_KEY_NODE_SUPPORTS_LAZY, "1", + PW_KEY_NODE_SUPPORTS_REQUEST, "1", NULL), data.path = argc > 1 ? argv1 : NULL; if (data.path)
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/examples/video-src.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/examples/video-src.c
Changed
@@ -194,8 +194,13 @@ interval.tv_sec = 0; interval.tv_nsec = 40 * SPA_NSEC_PER_MSEC; - pw_loop_update_timer(pw_main_loop_get_loop(data->loop), - data->timer, &timeout, &interval, false); + printf("driving:%d lazy:%d\n", + pw_stream_is_driving(data->stream), + pw_stream_is_lazy(data->stream)); + + if (pw_stream_is_driving(data->stream) != pw_stream_is_lazy(data->stream)) + pw_loop_update_timer(pw_main_loop_get_loop(data->loop), + data->timer, &timeout, &interval, false); break; } default: @@ -305,6 +310,7 @@ data.stream = pw_stream_new(data.core, "video-src", pw_properties_new( PW_KEY_MEDIA_CLASS, "Video/Source", + PW_KEY_NODE_SUPPORTS_REQUEST, "1", NULL)); params0 = spa_pod_builder_add_object(&b,
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/gst/gstpipewiredeviceprovider.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/gst/gstpipewiredeviceprovider.c
Changed
@@ -277,7 +277,7 @@ static void do_add_nodes(GstPipeWireDeviceProvider *self) { struct node_data *nd; - GList *new_devices = NULL; + g_autoptr (GList) new_devices = NULL; GList *l; spa_list_for_each(nd, &self->nodes, link) {
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/gst/gstpipewiresrc.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/gst/gstpipewiresrc.c
Changed
@@ -1004,7 +1004,9 @@ GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT, ("%s", error_string), ("This element did not produce valid caps")); + pw_thread_loop_lock (pwsrc->stream->core->loop); pw_stream_set_error (pwsrc->stream->pwstream, -EINVAL, "%s", error_string); + pw_thread_loop_unlock (pwsrc->stream->core->loop); return FALSE; } no_common_caps: @@ -1014,7 +1016,9 @@ GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT, ("%s", error_string), ("This element does not have formats in common with the peer")); + pw_thread_loop_lock (pwsrc->stream->core->loop); pw_stream_set_error (pwsrc->stream->pwstream, -EPIPE, "%s", error_string); + pw_thread_loop_unlock (pwsrc->stream->core->loop); return FALSE; } connect_error:
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain.c
Changed
@@ -620,9 +620,9 @@ #define DEFAULT_RATE 48000 struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support, - struct dsp_ops *dsp, const char *path, const char *config); + struct dsp_ops *dsp, const char *path, const struct spa_dict *info); struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support, - struct dsp_ops *dsp, const char *path, const char *config); + struct dsp_ops *dsp, const char *path, const struct spa_dict *info); struct plugin { struct spa_list link; @@ -762,6 +762,7 @@ struct pw_context *context; struct pw_impl_module *module; + struct pw_properties *props; struct spa_hook module_listener; @@ -1722,7 +1723,7 @@ pw_log_error("can't load plugin type '%s': %m", type); pl = NULL; } else { - pl = plugin_func(support, n_support, &impl->dsp, path, NULL); + pl = plugin_func(support, n_support, &impl->dsp, path, &impl->props->dict); } if (pl == NULL) goto exit; @@ -2339,6 +2340,7 @@ struct link *link; struct descriptor *desc; const struct fc_descriptor *d; + const struct fc_plugin *p; uint32_t i, j, max_samples = impl->quantum_limit; int res; float *sd, *dd; @@ -2348,28 +2350,37 @@ graph->instantiated = true; + /* first make instances */ spa_list_for_each(node, &graph->node_list, link) { - node_cleanup(node); desc = node->desc; d = desc->desc; - if (d->flags & FC_DESCRIPTOR_SUPPORTS_NULL_DATA) { - sd = dd = NULL; - } - else { - sd = impl->silence_data; - dd = impl->discard_data; - } + p = desc->plugin->plugin; for (i = 0; i < node->n_hndl; i++) { pw_log_info("instantiate %s %d rate:%lu", d->name, i, impl->rate); errno = EINVAL; - if ((node->hndli = d->instantiate(d, impl->rate, i, node->config)) == NULL) { + if ((node->hndli = d->instantiate(p, d, impl->rate, i, node->config)) == NULL) { pw_log_error("cannot create plugin instance %d rate:%lu: %m", i, impl->rate); res = -errno; goto error; } + } + } + + /* then link ports and activate */ + spa_list_for_each(node, &graph->node_list, link) { + desc = node->desc; + d = desc->desc; + if (d->flags & FC_DESCRIPTOR_SUPPORTS_NULL_DATA) { + sd = dd = NULL; + } + else { + sd = impl->silence_data; + dd = impl->discard_data; + } + for (i = 0; i < node->n_hndl; i++) { for (j = 0; j < desc->n_input; j++) { port = &node->input_portj; d->connect_port(node->hndli, port->p, sd); @@ -2898,6 +2909,7 @@ spa_list_consume(pl, &impl->plugin_func_list, link) free_plugin_func(pl); + pw_properties_free(impl->props); free(impl->silence_data); free(impl->discard_data); free(impl); @@ -2997,6 +3009,7 @@ pw_log_error( "can't create properties: %m"); goto error; } + impl->props = props; impl->capture_props = pw_properties_new(NULL, NULL); impl->playback_props = pw_properties_new(NULL, NULL); @@ -3021,6 +3034,8 @@ pw_context_get_properties(impl->context), "default.clock.quantum-limit", 8192u); + pw_properties_setf(props, "clock.quantum-limit", "%u", impl->quantum_limit); + impl->silence_data = calloc(impl->quantum_limit, sizeof(float)); if (impl->silence_data == NULL) { res = -errno; @@ -3122,7 +3137,6 @@ pw_log_error("can't connect: %m"); goto error; } - pw_properties_free(props); pw_proxy_add_listener((struct pw_proxy*)impl->core, &impl->core_proxy_listener, @@ -3140,7 +3154,6 @@ return 0; error: - pw_properties_free(props); impl_destroy(impl); return res; }
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/builtin_plugin.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/builtin_plugin.c
Changed
@@ -28,9 +28,13 @@ #define MAX_RATES 32u -static struct dsp_ops *dsp_ops; +struct plugin { + struct fc_plugin plugin; + struct dsp_ops *dsp_ops; +}; struct builtin { + struct plugin *plugin; unsigned long rate; float *port64; @@ -44,7 +48,7 @@ float accum; }; -static void *builtin_instantiate(const struct fc_descriptor * Descriptor, +static void *builtin_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor, unsigned long SampleRate, int index, const char *config) { struct builtin *impl; @@ -53,6 +57,7 @@ if (impl == NULL) return NULL; + impl->plugin = (struct plugin *) plugin; impl->rate = SampleRate; return impl; @@ -75,7 +80,7 @@ { struct builtin *impl = Instance; float *in = impl->port1, *out = impl->port0; - dsp_ops_copy(dsp_ops, out, in, SampleCount); + dsp_ops_copy(impl->plugin->dsp_ops, out, in, SampleCount); } static struct fc_port copy_ports = { @@ -124,7 +129,7 @@ srcn_src = in; gainsn_src++ = gain; } - dsp_ops_mix_gain(dsp_ops, out, src, gains, n_src, SampleCount); + dsp_ops_mix_gain(impl->plugin->dsp_ops, out, src, gains, n_src, SampleCount); } static struct fc_port mixer_ports = { @@ -274,7 +279,7 @@ * * } */ -static void *bq_instantiate(const struct fc_descriptor * Descriptor, +static void *bq_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor, unsigned long SampleRate, int index, const char *config) { struct builtin *impl; @@ -287,6 +292,7 @@ if (impl == NULL) return NULL; + impl->plugin = (struct plugin *) plugin; impl->rate = SampleRate; impl->b0 = impl->a0 = 1.0f; impl->type = bq_type_from_name(Descriptor->name); @@ -503,7 +509,7 @@ if (impl->freq != freq || impl->Q != Q || impl->gain != gain) bq_freq_update(impl, impl->type, freq, Q, gain); } - dsp_ops_biquad_run(dsp_ops, bq, out, in, samples); + dsp_ops_biquad_run(impl->plugin->dsp_ops, bq, out, in, samples); } /** bq_lowpass */ @@ -635,6 +641,7 @@ /** convolve */ struct convolver_impl { + struct plugin *plugin; unsigned long rate; float *port64; @@ -781,7 +788,7 @@ return samples; } -static float *resample_buffer(float *samples, int *n_samples, +static float *resample_buffer(struct dsp_ops *dsp_ops, float *samples, int *n_samples, unsigned long in_rate, unsigned long out_rate, uint32_t quality) { #ifdef HAVE_SPA_PLUGINS @@ -858,7 +865,7 @@ #endif } -static void * convolver_instantiate(const struct fc_descriptor * Descriptor, +static void * convolver_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor, unsigned long SampleRate, int index, const char *config) { struct convolver_impl *impl; @@ -982,9 +989,11 @@ rate = SampleRate; samples = read_closest(filenames, gain, delay, offset, length, channel, &rate, &n_samples); - if (samples != NULL && rate != SampleRate) - samples = resample_buffer(samples, &n_samples, + if (samples != NULL && rate != SampleRate) { + struct plugin *p = (struct plugin *) plugin; + samples = resample_buffer(p->dsp_ops, samples, &n_samples, rate, SampleRate, resample_quality); + } } for (i = 0; i < MAX_RATES; i++) @@ -1008,9 +1017,10 @@ if (impl == NULL) goto error; + impl->plugin = (struct plugin *) plugin; impl->rate = SampleRate; - impl->conv = convolver_new(dsp_ops, blocksize, tailsize, samples, n_samples); + impl->conv = convolver_new(impl->plugin->dsp_ops, blocksize, tailsize, samples, n_samples); if (impl->conv == NULL) goto error; @@ -1076,6 +1086,7 @@ /** delay */ struct delay_impl { + struct plugin *plugin; unsigned long rate; float *port4; @@ -1093,7 +1104,7 @@ free(impl); } -static void *delay_instantiate(const struct fc_descriptor * Descriptor, +static void *delay_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor, unsigned long SampleRate, int index, const char *config) { struct delay_impl *impl; @@ -1133,6 +1144,7 @@ if (impl == NULL) return NULL; + impl->plugin = (struct plugin *) plugin; impl->rate = SampleRate; impl->buffer_samples = (uint32_t)(max_delay * impl->rate); pw_log_info("max-delay:%f seconds rate:%lu samples:%d", max_delay, impl->rate, impl->buffer_samples); @@ -1311,7 +1323,7 @@ float *ctrl = impl->port3, *notify = impl->port2; if (in != NULL && out != NULL) - dsp_ops_linear(dsp_ops, out, in, mult, add, SampleCount); + dsp_ops_linear(impl->plugin->dsp_ops, out, in, mult, add, SampleCount); if (ctrl != NULL && notify != NULL) notify0 = ctrl0 * mult + add; @@ -1556,7 +1568,7 @@ srcn_src++ = in; } - dsp_ops_mult(dsp_ops, out, src, n_src, SampleCount); + dsp_ops_mult(impl->plugin->dsp_ops, out, src, n_src, SampleCount); } static struct fc_port mult_ports = { @@ -1742,14 +1754,18 @@ return NULL; } -static struct fc_plugin builtin_plugin = { - .make_desc = builtin_make_desc -}; +static void builtin_plugin_unload(struct fc_plugin *p) +{ + free(p); +} struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support, - struct dsp_ops *dsp, const char *plugin, const char *config) + struct dsp_ops *dsp, const char *plugin, const struct spa_dict *info) { - dsp_ops = dsp; + struct plugin *impl = calloc (1, sizeof (struct plugin)); + impl->plugin.make_desc = builtin_make_desc; + impl->plugin.unload = builtin_plugin_unload; + impl->dsp_ops = dsp; pffft_select_cpu(dsp->cpu_flags); - return &builtin_plugin; + return (struct fc_plugin *) impl; }
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/convolver.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/convolver.c
Changed
@@ -10,9 +10,9 @@ #include <math.h> -static struct dsp_ops *dsp; - struct convolver1 { + struct dsp_ops *dsp; + int blockSize; int segSize; int segCount; @@ -54,7 +54,7 @@ free(*((void **)p - 1)); } -static inline void fft_cpx_clear(float *v, int size) +static inline void fft_cpx_clear(struct dsp_ops *dsp, float *v, int size) { dsp_ops_clear(dsp, v, size * 2); } @@ -80,16 +80,16 @@ { int i; for (i = 0; i < conv->segCount; i++) - fft_cpx_clear(conv->segmentsi, conv->fftComplexSize); - dsp_ops_clear(dsp, conv->overlap, conv->blockSize); - dsp_ops_clear(dsp, conv->inputBuffer, conv->segSize); - fft_cpx_clear(conv->pre_mult, conv->fftComplexSize); - fft_cpx_clear(conv->conv, conv->fftComplexSize); + fft_cpx_clear(conv->dsp, conv->segmentsi, conv->fftComplexSize); + dsp_ops_clear(conv->dsp, conv->overlap, conv->blockSize); + dsp_ops_clear(conv->dsp, conv->inputBuffer, conv->segSize); + fft_cpx_clear(conv->dsp, conv->pre_mult, conv->fftComplexSize); + fft_cpx_clear(conv->dsp, conv->conv, conv->fftComplexSize); conv->inputBufferFill = 0; conv->current = 0; } -static struct convolver1 *convolver1_new(int block, const float *ir, int irlen) +static struct convolver1 *convolver1_new(struct dsp_ops *dsp, int block, const float *ir, int irlen) { struct convolver1 *conv; int i; @@ -107,15 +107,16 @@ if (irlen == 0) return conv; + conv->dsp = dsp; conv->blockSize = next_power_of_two(block); conv->segSize = 2 * conv->blockSize; conv->segCount = (irlen + conv->blockSize-1) / conv->blockSize; conv->fftComplexSize = (conv->segSize / 2) + 1; - conv->fft = dsp_ops_fft_new(dsp, conv->segSize, true); + conv->fft = dsp_ops_fft_new(conv->dsp, conv->segSize, true); if (conv->fft == NULL) goto error; - conv->ifft = dsp_ops_fft_new(dsp, conv->segSize, true); + conv->ifft = dsp_ops_fft_new(conv->dsp, conv->segSize, true); if (conv->ifft == NULL) goto error; @@ -133,11 +134,11 @@ conv->segmentsi = fft_cpx_alloc(conv->fftComplexSize); conv->segmentsIri = fft_cpx_alloc(conv->fftComplexSize); - dsp_ops_copy(dsp, conv->fft_buffer, &iri * conv->blockSize, copy); + dsp_ops_copy(conv->dsp, conv->fft_buffer, &iri * conv->blockSize, copy); if (copy < conv->segSize) - dsp_ops_clear(dsp, conv->fft_buffer + copy, conv->segSize - copy); + dsp_ops_clear(conv->dsp, conv->fft_buffer + copy, conv->segSize - copy); - dsp_ops_fft_run(dsp, conv->fft, 1, conv->fft_buffer, conv->segmentsIri); + dsp_ops_fft_run(conv->dsp, conv->fft, 1, conv->fft_buffer, conv->segmentsIri); } conv->pre_mult = fft_cpx_alloc(conv->fftComplexSize); conv->conv = fft_cpx_alloc(conv->fftComplexSize); @@ -166,9 +167,9 @@ fft_cpx_free(conv->segmentsIri); } if (conv->fft) - dsp_ops_fft_free(dsp, conv->fft); + dsp_ops_fft_free(conv->dsp, conv->fft); if (conv->ifft) - dsp_ops_fft_free(dsp, conv->ifft); + dsp_ops_fft_free(conv->dsp, conv->ifft); if (conv->fft_buffer) fft_free(conv->fft_buffer); free(conv->segments); @@ -185,7 +186,7 @@ int i, processed = 0; if (conv == NULL || conv->segCount == 0) { - dsp_ops_clear(dsp, output, len); + dsp_ops_clear(conv->dsp, output, len); return len; } @@ -193,17 +194,17 @@ const int processing = SPA_MIN(len - processed, conv->blockSize - conv->inputBufferFill); const int inputBufferPos = conv->inputBufferFill; - dsp_ops_copy(dsp, conv->inputBuffer + inputBufferPos, input + processed, processing); + dsp_ops_copy(conv->dsp, conv->inputBuffer + inputBufferPos, input + processed, processing); if (inputBufferPos == 0 && processing < conv->blockSize) - dsp_ops_clear(dsp, conv->inputBuffer + processing, conv->blockSize - processing); + dsp_ops_clear(conv->dsp, conv->inputBuffer + processing, conv->blockSize - processing); - dsp_ops_fft_run(dsp, conv->fft, 1, conv->inputBuffer, conv->segmentsconv->current); + dsp_ops_fft_run(conv->dsp, conv->fft, 1, conv->inputBuffer, conv->segmentsconv->current); if (conv->segCount > 1) { if (conv->inputBufferFill == 0) { int indexAudio = (conv->current + 1) % conv->segCount; - dsp_ops_fft_cmul(dsp, conv->fft, conv->pre_mult, + dsp_ops_fft_cmul(conv->dsp, conv->fft, conv->pre_mult, conv->segmentsIr1, conv->segmentsindexAudio, conv->fftComplexSize, conv->scale); @@ -211,7 +212,7 @@ for (i = 2; i < conv->segCount; i++) { indexAudio = (conv->current + i) % conv->segCount; - dsp_ops_fft_cmuladd(dsp, conv->fft, + dsp_ops_fft_cmuladd(conv->dsp, conv->fft, conv->pre_mult, conv->pre_mult, conv->segmentsIri, @@ -219,30 +220,30 @@ conv->fftComplexSize, conv->scale); } } - dsp_ops_fft_cmuladd(dsp, conv->fft, + dsp_ops_fft_cmuladd(conv->dsp, conv->fft, conv->conv, conv->pre_mult, conv->segmentsconv->current, conv->segmentsIr0, conv->fftComplexSize, conv->scale); } else { - dsp_ops_fft_cmul(dsp, conv->fft, + dsp_ops_fft_cmul(conv->dsp, conv->fft, conv->conv, conv->segmentsconv->current, conv->segmentsIr0, conv->fftComplexSize, conv->scale); } - dsp_ops_fft_run(dsp, conv->ifft, -1, conv->conv, conv->fft_buffer); + dsp_ops_fft_run(conv->dsp, conv->ifft, -1, conv->conv, conv->fft_buffer); - dsp_ops_sum(dsp, output + processed, conv->fft_buffer + inputBufferPos, + dsp_ops_sum(conv->dsp, output + processed, conv->fft_buffer + inputBufferPos, conv->overlap + inputBufferPos, processing); conv->inputBufferFill += processing; if (conv->inputBufferFill == conv->blockSize) { conv->inputBufferFill = 0; - dsp_ops_copy(dsp, conv->overlap, conv->fft_buffer + conv->blockSize, conv->blockSize); + dsp_ops_copy(conv->dsp, conv->overlap, conv->fft_buffer + conv->blockSize, conv->blockSize); conv->current = (conv->current > 0) ? (conv->current - 1) : (conv->segCount - 1); } @@ -254,6 +255,7 @@ struct convolver { + struct dsp_ops *dsp; int headBlockSize; int tailBlockSize; struct convolver1 *headConvolver; @@ -274,13 +276,13 @@ convolver1_reset(conv->headConvolver); if (conv->tailConvolver0) { convolver1_reset(conv->tailConvolver0); - dsp_ops_clear(dsp, conv->tailOutput0, conv->tailBlockSize); - dsp_ops_clear(dsp, conv->tailPrecalculated0, conv->tailBlockSize); + dsp_ops_clear(conv->dsp, conv->tailOutput0, conv->tailBlockSize); + dsp_ops_clear(conv->dsp, conv->tailPrecalculated0, conv->tailBlockSize); } if (conv->tailConvolver) { convolver1_reset(conv->tailConvolver); - dsp_ops_clear(dsp, conv->tailOutput, conv->tailBlockSize); - dsp_ops_clear(dsp, conv->tailPrecalculated, conv->tailBlockSize); + dsp_ops_clear(conv->dsp, conv->tailOutput, conv->tailBlockSize); + dsp_ops_clear(conv->dsp, conv->tailPrecalculated, conv->tailBlockSize); } conv->tailInputFill = 0; conv->precalculatedPos = 0; @@ -291,8 +293,6 @@ struct convolver *conv; int head_ir_len; - dsp = dsp_ops; - if (head_block == 0 || tail_block == 0) return NULL; @@ -310,22 +310,23 @@ if (irlen == 0) return conv; + conv->dsp = dsp_ops; conv->headBlockSize = next_power_of_two(head_block); conv->tailBlockSize = next_power_of_two(tail_block); head_ir_len = SPA_MIN(irlen, conv->tailBlockSize); - conv->headConvolver = convolver1_new(conv->headBlockSize, ir, head_ir_len); + conv->headConvolver = convolver1_new(dsp_ops, conv->headBlockSize, ir, head_ir_len); if (irlen > conv->tailBlockSize) { int conv1IrLen = SPA_MIN(irlen - conv->tailBlockSize, conv->tailBlockSize); - conv->tailConvolver0 = convolver1_new(conv->headBlockSize, ir + conv->tailBlockSize, conv1IrLen); + conv->tailConvolver0 = convolver1_new(dsp_ops, conv->headBlockSize, ir + conv->tailBlockSize, conv1IrLen); conv->tailOutput0 = fft_alloc(conv->tailBlockSize); conv->tailPrecalculated0 = fft_alloc(conv->tailBlockSize); } if (irlen > 2 * conv->tailBlockSize) { int tailIrLen = irlen - (2 * conv->tailBlockSize); - conv->tailConvolver = convolver1_new(conv->tailBlockSize, ir + (2 * conv->tailBlockSize), tailIrLen); + conv->tailConvolver = convolver1_new(dsp_ops, conv->tailBlockSize, ir + (2 * conv->tailBlockSize), tailIrLen); conv->tailOutput = fft_alloc(conv->tailBlockSize); conv->tailPrecalculated = fft_alloc(conv->tailBlockSize); } @@ -366,16 +367,16 @@ int processing = SPA_MIN(remaining, conv->headBlockSize - (conv->tailInputFill % conv->headBlockSize)); if (conv->tailPrecalculated0) - dsp_ops_sum(dsp, &outputprocessed, &outputprocessed, + dsp_ops_sum(conv->dsp, &outputprocessed, &outputprocessed, &conv->tailPrecalculated0conv->precalculatedPos, processing); if (conv->tailPrecalculated) - dsp_ops_sum(dsp, &outputprocessed, &outputprocessed, + dsp_ops_sum(conv->dsp, &outputprocessed, &outputprocessed, &conv->tailPrecalculatedconv->precalculatedPos, processing); conv->precalculatedPos += processing; - dsp_ops_copy(dsp, conv->tailInput + conv->tailInputFill, input + processed, processing); + dsp_ops_copy(conv->dsp, conv->tailInput + conv->tailInputFill, input + processed, processing); conv->tailInputFill += processing; if (conv->tailPrecalculated0 && (conv->tailInputFill % conv->headBlockSize == 0)) {
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/ladspa_plugin.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/ladspa_plugin.c
Changed
@@ -29,7 +29,7 @@ const LADSPA_Descriptor *d; }; -static void *ladspa_instantiate(const struct fc_descriptor *desc, +static void *ladspa_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor *desc, unsigned long SampleRate, int index, const char *config) { struct descriptor *d = (struct descriptor *)desc; @@ -210,7 +210,7 @@ } struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support, - struct dsp_ops *dsp, const char *plugin, const char *config) + struct dsp_ops *dsp, const char *plugin, const struct spa_dict *info) { struct fc_plugin *pl = NULL;
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/lv2_plugin.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/lv2_plugin.c
Changed
@@ -80,7 +80,7 @@ URITable *table = (URITable*)handle; if (urid > 0 && urid <= pw_array_get_len(&table->array, char*)) - return *pw_array_get_unchecked(&table->array, urid, char*); + return *pw_array_get_unchecked(&table->array, urid - 1, char*); return NULL; } @@ -278,7 +278,7 @@ return LV2_WORKER_SUCCESS; } -static void *lv2_instantiate(const struct fc_descriptor *desc, +static void *lv2_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor *desc, unsigned long SampleRate, int index, const char *config) { struct descriptor *d = (struct descriptor*)desc; @@ -460,7 +460,7 @@ SPA_EXPORT struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support, - struct dsp_ops *ops, const char *plugin_uri, const char *config) + struct dsp_ops *dsp, const char *plugin_uri, const struct spa_dict *info) { struct context *c; const LilvPlugins *plugins;
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/plugin.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/plugin.h
Changed
@@ -51,7 +51,7 @@ uint32_t n_ports; struct fc_port *ports; - void *(*instantiate) (const struct fc_descriptor *desc, + void *(*instantiate) (const struct fc_plugin *plugin, const struct fc_descriptor *desc, unsigned long SampleRate, int index, const char *config); void (*cleanup) (void *instance); @@ -80,7 +80,7 @@ #define FC_PLUGIN_LOAD_FUNC "pipewire__filter_chain_plugin_load" typedef struct fc_plugin *(fc_plugin_load_func)(const struct spa_support *support, uint32_t n_support, - struct dsp_ops *dsp, const char *path, const char *config); + struct dsp_ops *dsp, const char *path, const struct spa_dict *info); #endif /* PLUGIN_H */
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/sofa_plugin.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/sofa_plugin.c
Changed
@@ -14,13 +14,16 @@ #include <mysofa.h> -#define MAX_SAMPLES 8192u - -static struct dsp_ops *dsp_ops; -static struct spa_loop *data_loop; -static struct spa_loop *main_loop; +struct plugin { + struct fc_plugin plugin; + struct dsp_ops *dsp_ops; + struct spa_loop *data_loop; + struct spa_loop *main_loop; + uint32_t quantum_limit; +}; struct spatializer_impl { + struct plugin *plugin; unsigned long rate; float *port6; int n_samples, blocksize, tailsize; @@ -32,7 +35,7 @@ struct convolver *r_conv3; }; -static void * spatializer_instantiate(const struct fc_descriptor * Descriptor, +static void * spatializer_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor, unsigned long SampleRate, int index, const char *config) { struct spatializer_impl *impl; @@ -58,6 +61,7 @@ errno = ENOMEM; return NULL; } + impl->plugin = (struct plugin *) plugin; while (spa_json_get_string(&it1, key, sizeof(key)) > 0) { if (spa_streq(key, "blocksize")) { @@ -175,8 +179,8 @@ pw_log_info("using n_samples:%u %d:%d blocksize sofa:%s", impl->n_samples, impl->blocksize, impl->tailsize, filename); - impl->tmp0 = calloc(MAX_SAMPLES, sizeof(float)); - impl->tmp1 = calloc(MAX_SAMPLES, sizeof(float)); + impl->tmp0 = calloc(impl->plugin->quantum_limit, sizeof(float)); + impl->tmp1 = calloc(impl->plugin->quantum_limit, sizeof(float)); impl->rate = SampleRate; return impl; error: @@ -239,9 +243,9 @@ if (impl->r_conv2) convolver_free(impl->r_conv2); - impl->l_conv2 = convolver_new(dsp_ops, impl->blocksize, impl->tailsize, + impl->l_conv2 = convolver_new(impl->plugin->dsp_ops, impl->blocksize, impl->tailsize, left_ir, impl->n_samples); - impl->r_conv2 = convolver_new(dsp_ops, impl->blocksize, impl->tailsize, + impl->r_conv2 = convolver_new(impl->plugin->dsp_ops, impl->blocksize, impl->tailsize, right_ir, impl->n_samples); free(left_ir); @@ -251,7 +255,7 @@ pw_log_error("reloading left or right convolver failed"); return; } - spa_loop_invoke(data_loop, do_switch, 1, NULL, 0, true, impl); + spa_loop_invoke(impl->plugin->data_loop, do_switch, 1, NULL, 0, true, impl); } struct free_data { @@ -275,7 +279,7 @@ struct spatializer_impl *impl = Instance; if (impl->interpolate) { - uint32_t len = SPA_MIN(SampleCount, MAX_SAMPLES); + uint32_t len = SPA_MIN(SampleCount, impl->plugin->quantum_limit); struct free_data free_data; float *l = impl->tmp0, *r = impl->tmp1; @@ -296,7 +300,7 @@ impl->l_conv1 = impl->r_conv1 = NULL; impl->interpolate = false; - spa_loop_invoke(main_loop, do_free, 1, &free_data, sizeof(free_data), false, impl); + spa_loop_invoke(impl->plugin->main_loop, do_free, 1, &free_data, sizeof(free_data), false, impl); } else if (impl->l_conv0 && impl->r_conv0) { convolver_run(impl->l_conv0, impl->port2, impl->port0, SampleCount); convolver_run(impl->r_conv0, impl->port2, impl->port1, SampleCount); @@ -413,19 +417,33 @@ return NULL; } -static struct fc_plugin builtin_plugin = { - .make_desc = sofa_make_desc -}; +static void sofa_plugin_unload(struct fc_plugin *p) +{ + free(p); +} SPA_EXPORT struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support, - struct dsp_ops *dsp, const char *plugin, const char *config) + struct dsp_ops *dsp, const char *plugin, const struct spa_dict *info) { - dsp_ops = dsp; + struct plugin *impl = calloc(1, sizeof (struct plugin)); + + impl->plugin.make_desc = sofa_make_desc; + impl->plugin.unload = sofa_plugin_unload; + + impl->quantum_limit = 8192u; + + for (uint32_t i = 0; info && i < info->n_items; i++) { + const char *k = info->itemsi.key; + const char *s = info->itemsi.value; + if (spa_streq(k, "clock.quantum-limit")) + spa_atou32(s, &impl->quantum_limit, 0); + } + impl->dsp_ops = dsp; pffft_select_cpu(dsp->cpu_flags); - data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop); - main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop); + impl->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop); + impl->main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop); - return &builtin_plugin; + return (struct fc_plugin *) impl; }
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-jack-tunnel.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-jack-tunnel.c
Changed
@@ -19,6 +19,7 @@ #include <spa/utils/result.h> #include <spa/utils/string.h> #include <spa/utils/json.h> +#include <spa/utils/ratelimit.h> #include <spa/debug/types.h> #include <spa/pod/builder.h> #include <spa/param/audio/format-utils.h> @@ -184,6 +185,8 @@ struct spa_hook core_proxy_listener; struct spa_hook core_listener; + struct spa_ratelimit rate_limit; + struct spa_io_position *position; struct stream source; @@ -192,7 +195,7 @@ uint32_t samplerate; jack_client_t *client; - jack_nframes_t frame_time; + jack_nframes_t current_frames; uint32_t pw_xrun; uint32_t jack_xrun; @@ -355,7 +358,7 @@ else do_volume(dst, src, &s->volume, i, n_samples); } - pw_log_trace_fp("done %u %u", impl->frame_time, n_samples); + pw_log_trace_fp("done %u %u", impl->current_frames, n_samples); if (impl->mode & MODE_SINK) { impl->done = true; jack.cycle_signal(impl->client, 0); @@ -369,7 +372,7 @@ uint32_t i, n_samples = position->clock.duration; if (impl->mode == MODE_SOURCE && !impl->triggered) { - pw_log_trace_fp("done %u", impl->frame_time); + pw_log_trace_fp("done %u", impl->current_frames); impl->done = true; jack.cycle_signal(impl->client, 0); return; @@ -687,35 +690,40 @@ jack_nframes_t nframes; while (true) { + jack_nframes_t current_frames; + jack_time_t current_usecs; + jack_time_t next_usecs; + float period_usecs; + nframes = jack.cycle_wait (impl->client); + jack.get_cycle_times(impl->client, + ¤t_frames, ¤t_usecs, + &next_usecs, &period_usecs); + + impl->current_frames = current_frames; + source_running = impl->source.running; sink_running = impl->sink.running; - impl->frame_time = jack.frame_time(impl->client); - pw_log_trace_fp("process %d %u %u %p %d", nframes, source_running, - sink_running, impl->position, impl->frame_time); + sink_running, impl->position, current_frames); if (impl->new_xrun) { - pw_log_warn("Xrun JACK:%u PipeWire:%u", impl->jack_xrun, impl->pw_xrun); + int suppressed; + if ((suppressed = spa_ratelimit_test(&impl->rate_limit, current_usecs)) >= 0) { + pw_log_warn("Xrun: current_frames:%u JACK:%u PipeWire:%u (%d suppressed)", + current_frames, impl->jack_xrun, impl->pw_xrun, suppressed); + } impl->new_xrun = false; } if (impl->position) { struct spa_io_clock *c = &impl->position->clock; - jack_nframes_t current_frames; - jack_time_t current_usecs; - jack_time_t next_usecs; - float period_usecs; jack_position_t pos; uint64_t t1, t2, t3; int64_t d1; - jack.get_cycle_times(impl->client, - ¤t_frames, ¤t_usecs, - &next_usecs, &period_usecs); - /* convert from JACK (likely MONOTONIC_RAW) to MONOTONIC */ t1 = get_time_nsec(impl) / 1000; t2 = jack.get_time(); @@ -1081,6 +1089,9 @@ impl->main_loop = pw_context_get_main_loop(context); impl->system = impl->main_loop->system; + impl->rate_limit.interval = 2 * SPA_USEC_PER_SEC; + impl->rate_limit.burst = 1; + impl->source.impl = impl; impl->source.direction = PW_DIRECTION_OUTPUT; impl->sink.impl = impl;
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-parametric-equalizer.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-parametric-equalizer.c
Changed
@@ -8,6 +8,7 @@ #include "config.h" #include <spa/utils/result.h> +#include <spa/utils/json.h> #include <spa/param/audio/raw.h> #include <pipewire/impl.h> @@ -147,7 +148,8 @@ .destroy = filter_chain_module_destroy, }; -void init_eq_node(FILE *f, const char *node_desc) { +void init_eq_node(FILE *f, const char *node_desc) +{ fprintf(f, "{\n"); fprintf(f, "node.description = \"%s\"\n", node_desc); fprintf(f, "media.name = \"%s\"\n", node_desc); @@ -155,7 +157,10 @@ fprintf(f, "nodes = \n"); } -void add_eq_node(FILE *f, struct eq_node_param *param, uint32_t eq_band_idx) { +void add_eq_node(FILE *f, struct eq_node_param *param, uint32_t eq_band_idx) +{ + char str164, str264; + fprintf(f, "{\n"); fprintf(f, "type = builtin\n"); fprintf(f, "name = eq_band_%d\n", eq_band_idx); @@ -170,12 +175,15 @@ fprintf(f, "label = bq_peaking\n"); } - fprintf(f, "control = { \"Freq\" = %d \"Q\" = %f \"Gain\" = %f }\n", param->freq, param->q_fact, param->gain); + fprintf(f, "control = { \"Freq\" = %d \"Q\" = %s \"Gain\" = %s }\n", param->freq, + spa_json_format_float(str1, sizeof(str1), param->q_fact), + spa_json_format_float(str2, sizeof(str2), param->gain)); fprintf(f, "}\n"); } -void end_eq_node(struct impl *impl, FILE *f, uint32_t number_of_nodes) { +void end_eq_node(struct impl *impl, FILE *f, uint32_t number_of_nodes) +{ fprintf(f, "\n"); fprintf(f, "links = \n"); @@ -266,7 +274,9 @@ * Use a field width of 6 for gain and Q to account for any * possible zeros. */ - if (sscanf(line, "%*s %*d: %3s %3s %*s %5d %*s %*s %6f %*s %*c %6f", eq_param.filter, eq_param.filter_type, &eq_param.freq, &eq_param.gain, &eq_param.q_fact) == 5) { + if (sscanf(line, "%*s %*d: %3s %3s %*s %5d %*s %*s %6f %*s %*c %6f", + eq_param.filter, eq_param.filter_type, &eq_param.freq, + &eq_param.gain, &eq_param.q_fact) == 5) { if (strcmp(eq_param.filter, "ON") == 0) { add_eq_node(memstream, &eq_param, eq_band_idx);
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-profiler.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-profiler.c
Changed
@@ -245,10 +245,10 @@ spa_pod_builder_add_struct(&b, SPA_POD_Int(t->id), SPA_POD_String(t->name), - SPA_POD_Long(a->signal_time), - SPA_POD_Long(na->signal_time), - SPA_POD_Long(na->awake_time), - SPA_POD_Long(na->finish_time), + SPA_POD_Long(a->prev_signal_time), + SPA_POD_Long(n->async ? na->prev_signal_time : na->signal_time), + SPA_POD_Long(n->async ? na->prev_awake_time : na->awake_time), + SPA_POD_Long(n->async ? na->prev_finish_time : na->finish_time), SPA_POD_Int(na->status), SPA_POD_Fraction(&latency), SPA_POD_Int(na->xrun_count));
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-protocol-pulse/manager.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-protocol-pulse/manager.c
Changed
@@ -809,7 +809,7 @@ value = NULL; } - pw_metadata_set_property(metadata->proxy, + pw_metadata_set_property((struct pw_metadata*)metadata->proxy, subject, key, type, value); return 0; }
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-protocol-pulse/pulse-server.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -2161,6 +2161,7 @@ uint32_t channel; struct timeval tv, now; struct stream *stream; + uint64_t delay; int res; if ((res = message_get(m, @@ -2182,9 +2183,11 @@ gettimeofday(&now, NULL); + delay = SPA_CLAMP(stream->delay, 0, INT64_MAX); + reply = reply_new(client, tag); message_put(reply, - TAG_USEC, stream->delay, /* sink latency + queued samples */ + TAG_USEC, delay, /* sink latency + queued samples */ TAG_USEC, 0LL, /* always 0 */ TAG_BOOLEAN, stream->playing_for > 0 && !stream->corked, /* playing state */ @@ -2210,6 +2213,7 @@ uint32_t channel; struct timeval tv, now; struct stream *stream; + uint64_t delay; int res; if ((res = message_get(m, @@ -2229,10 +2233,13 @@ gettimeofday(&now, NULL); + + delay = SPA_CLAMP(stream->delay, 0, INT64_MAX); + reply = reply_new(client, tag); message_put(reply, TAG_USEC, 0LL, /* monitor latency */ - TAG_USEC, stream->delay, /* source latency + queued */ + TAG_USEC, delay, /* source latency + queued */ TAG_BOOLEAN, !stream->corked, /* playing state */ TAG_TIMEVAL, &tv, TAG_TIMEVAL, &now,
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-protocol-pulse/server.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-protocol-pulse/server.c
Changed
@@ -356,6 +356,7 @@ int client_fd, val; struct client *client = NULL; const char *client_access = NULL; + const char *error_reason = NULL; pid_t pid; length = sizeof(name); @@ -374,6 +375,7 @@ if (server->n_clients >= server->max_clients) { close(client_fd); + error_reason = "too many client application connections"; errno = ECONNREFUSED; goto error; } @@ -487,7 +489,9 @@ return; error: - pw_log_error("server %p: failed to create client: %m", server); + pw_log_error("server %p: %s: %m", server, + error_reason ? error_reason : "failed to create client"); + if (client) client_free(client); }
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-rtp-source.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-rtp-source.c
Changed
@@ -162,6 +162,9 @@ socklen_t src_len; struct spa_source *source; + uint8_t *buffer; + size_t buffer_size; + unsigned receiving:1; unsigned last_receiving:1; }; @@ -171,17 +174,16 @@ { struct impl *impl = data; ssize_t len; - uint8_t buffer2048; if (mask & SPA_IO_IN) { - if ((len = recv(fd, buffer, sizeof(buffer), 0)) < 0) + if ((len = recv(fd, impl->buffer, impl->buffer_size, 0)) < 0) goto receive_error; if (len < 12) goto short_packet; if (SPA_LIKELY(impl->stream)) { - if (rtp_stream_receive_packet(impl->stream, buffer, len) < 0) + if (rtp_stream_receive_packet(impl->stream, impl->buffer, len) < 0) goto receive_error; } @@ -193,7 +195,7 @@ pw_log_warn("recv error: %m"); return; short_packet: - pw_log_warn("short packet received"); + pw_log_warn("short packet of len %zd received", len); return; } @@ -477,6 +479,7 @@ pw_properties_free(impl->stream_props); pw_properties_free(impl->props); + free(impl->buffer); free(impl->ifname); free(impl); } @@ -663,6 +666,14 @@ goto out; } + impl->buffer_size = rtp_stream_get_mtu(impl->stream); + impl->buffer = calloc(1, impl->buffer_size); + if (impl->buffer == NULL) { + res = -errno; + pw_log_error("can't create packet buffer of size %zd: %m", impl->buffer_size); + goto out; + } + pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl); pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_info));
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-rtp/midi.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-rtp/midi.c
Changed
@@ -354,7 +354,7 @@ struct rtp_header header; struct rtp_midi_header midi_header; struct iovec iov3; - uint32_t len, prev_offset, base; + uint32_t len, prev_offset, base, max_size; spa_zero(header); header.v = 2; @@ -371,6 +371,7 @@ iov2.iov_len = 0; prev_offset = len = base = 0; + max_size = impl->payload_size - sizeof(midi_header); SPA_POD_SEQUENCE_FOREACH(sequence, c) { void *ev; @@ -384,7 +385,7 @@ offset = c->offset * impl->rate / rate; - if (len > 0 && (len + size > impl->mtu || + if (len > 0 && (len + size > max_size || offset - base > impl->psamples)) { /* flush packet when we have one and when it's either * too large or has too much data. */
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-rtp/stream.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-rtp/stream.c
Changed
@@ -69,6 +69,7 @@ uint32_t ts_offset; uint32_t psamples; uint32_t mtu; + uint32_t payload_size; struct spa_ringbuffer ring; uint8_t bufferBUFFER_SIZE; @@ -439,6 +440,11 @@ impl->payload = pw_properties_get_uint32(props, "rtp.payload", impl->payload); impl->mtu = pw_properties_get_uint32(props, "net.mtu", DEFAULT_MTU); + if (impl->mtu <= PACKET_HEADER_SIZE) { + pw_log_error("invalid MTU %d, using %d", impl->mtu, DEFAULT_MTU); + impl->mtu = DEFAULT_MTU; + } + impl->payload_size = impl->mtu - PACKET_HEADER_SIZE; impl->seq = pw_rand32(); @@ -476,7 +482,7 @@ pw_log_warn("rtp.ptime doesn't match rtp.framecount. Choosing rtp.ptime"); } } else { - impl->psamples = impl->mtu / impl->stride; + impl->psamples = impl->payload_size / impl->stride; impl->psamples = SPA_CLAMP(impl->psamples, min_samples, max_samples); if (direction == PW_DIRECTION_INPUT) { pw_properties_set(props, "rtp.ptime", @@ -651,10 +657,15 @@ uint16_t rtp_stream_get_seq(struct rtp_stream *s) { struct impl *impl = (struct impl*)s; - return impl->seq; } +size_t rtp_stream_get_mtu(struct rtp_stream *s) +{ + struct impl *impl = (struct impl*)s; + return impl->mtu; +} + void rtp_stream_set_first(struct rtp_stream *s) { struct impl *impl = (struct impl*)s;
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-rtp/stream.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-rtp/stream.h
Changed
@@ -19,6 +19,9 @@ #define ERROR_MSEC 2.0f #define DEFAULT_SESS_LATENCY 100.0f +/* 28 bytes IP/UDP, 12 bytes RTP header */ +#define PACKET_HEADER_SIZE (12+28) + #define DEFAULT_MTU 1280 #define DEFAULT_MIN_PTIME 2.0f #define DEFAULT_MAX_PTIME 20.0f @@ -52,6 +55,8 @@ uint16_t rtp_stream_get_seq(struct rtp_stream *s); +size_t rtp_stream_get_mtu(struct rtp_stream *s); + void rtp_stream_set_first(struct rtp_stream *s); void rtp_stream_set_error(struct rtp_stream *s, int res, const char *error);
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/context.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/context.c
Changed
@@ -1637,6 +1637,7 @@ uint64_t quantum_stamp = 0, rate_stamp = 0; bool force_rate, force_quantum, restore_rate = false, restore_quantum = false; bool do_reconfigure = false, need_resume, was_target_pending; + bool have_request = false; const uint32_t *node_rates; uint32_t node_n_rates, node_def_rate; uint32_t node_max_quantum, node_min_quantum, node_def_quantum, node_rate_quantum; @@ -1705,6 +1706,9 @@ context, s, running, s->runnable, rate.num, rate.denom, latency.num, latency.denom, s->name); + if (running && s != n && s->supports_request > 0) + have_request = true; + s->moved = false; } @@ -1861,6 +1865,9 @@ n->target_rate = n->rt.position->clock.target_rate; } + SPA_FLAG_UPDATE(n->rt.position->clock.flags, + SPA_IO_CLOCK_FLAG_LAZY, have_request && n->supports_lazy > 0); + pw_log_debug("%p: driver %p running:%d runnable:%d quantum:%u rate:%u (%"PRIu64"/%u)'%s'", context, n, running, n->runnable, target_quantum, target_rate, n->rt.position->clock.target_duration,
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/filter.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/filter.c
Changed
@@ -2064,6 +2064,12 @@ return filter->node->driving; } +SPA_EXPORT +bool pw_filter_is_lazy(struct pw_filter *filter) +{ + return filter->node->lazy; +} + static int do_trigger_process(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data)
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/filter.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/filter.h
Changed
@@ -249,6 +249,10 @@ * available (output) or needed (input). Since 0.3.66 */ bool pw_filter_is_driving(struct pw_filter *filter); +/** Check if the graph is using lazy scheduling. + * Since 1.2.7 */ +bool pw_filter_is_lazy(struct pw_filter *filter); + /** Trigger a push/pull on the filter. One iteration of the graph will * be scheduled and process() will be called. Since 0.3.66 */ int pw_filter_trigger_process(struct pw_filter *filter);
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/impl-node.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/impl-node.c
Changed
@@ -324,6 +324,9 @@ pw_log_debug("%p: start node driving:%d driver:%d prepared:%d", this, this->driving, this->driver, this->rt.prepared); + this->lazy = this->rt.position && SPA_FLAG_IS_SET(this->rt.position->clock.flags, + SPA_IO_CLOCK_FLAG_LAZY); + if (!(this->driving && this->driver)) { impl->pending_play = true; res = spa_node_send_command(this->node, @@ -758,6 +761,14 @@ spa_list_for_each_safe(n, t, &context->driver_list, driver_link) { if (n->priority_driver < node->priority_driver) break; + if (n->priority_driver == 0 && node->priority_driver == 0) { + /* no priority is set, we prefer the driver that does + * lazy scheduling. */ + if (n->supports_request > 0 && node->supports_lazy > 0) { + if (n->supports_request <= node->supports_lazy) + break; + } + } } spa_list_append(&n->driver_link, &node->driver_link); pw_context_emit_driver_added(context, node); @@ -1122,6 +1133,8 @@ } } } + node->supports_lazy = pw_properties_get_uint32(node->properties, PW_KEY_NODE_SUPPORTS_LAZY, 0); + node->supports_request = pw_properties_get_uint32(node->properties, PW_KEY_NODE_SUPPORTS_REQUEST, 0); if ((str = pw_properties_get(node->properties, PW_KEY_NODE_NAME)) && (node->name == NULL || !spa_streq(node->name, str))) { @@ -2149,9 +2162,11 @@ } else { all_ready &= ta->pending_sync == false; } + ta->prev_signal_time = ta->signal_time; + ta->prev_awake_time = ta->awake_time; + ta->prev_finish_time = ta->finish_time; } - a->prev_signal_time = a->signal_time; node->driver_start = nsec; a->sync_timeout = SPA_MIN(min_timeout, DEFAULT_SYNC_TIMEOUT);
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/keys.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/keys.h
Changed
@@ -190,6 +190,15 @@ #define PW_KEY_NODE_DRIVER "node.driver" /**< node can drive the graph. When the node is * selected as the driver, it needs to start * the graph periodically. */ +#define PW_KEY_NODE_SUPPORTS_LAZY "node.supports-lazy" /**< the node can be a lazy driver. It will listen + * to RequestProcess commands and take them into + * account when deciding to start the graph. + * A value of 0 disables support, a value of > 0 + * enables with increasing preference. */ +#define PW_KEY_NODE_SUPPORTS_REQUEST "node.supports-request" /**< The node supports emiting RequestProcess events + * when it wants the graph to be scheduled. + * A value of 0 disables support, a value of > 0 + * enables with increasing preference. */ #define PW_KEY_NODE_DRIVER_ID "node.driver-id" /**< the node id of the node assigned as driver * for this node */ #define PW_KEY_NODE_ASYNC "node.async" /**< the node wants async scheduling */
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/private.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/private.h
Changed
@@ -608,7 +608,10 @@ uint32_t segment_owner16; /* id of owners for each segment info struct. * nodes that want to update segment info need to * CAS their node id in this array. */ - uint32_t padding11; /* must be 0 */ + uint64_t prev_awake_time; + uint64_t prev_finish_time; + uint32_t padding7; /* must be 0 */ + uint32_t client_version; /* verions of client, see above */ uint32_t server_version; /* verions of server, see above */ @@ -740,6 +743,9 @@ char *name; /** for debug */ + uint32_t supports_lazy; /**< lazy driver preference */ + uint32_t supports_request; /**< request follower preference */ + uint32_t priority_driver; /** priority for being driver */ char **groups; /** groups to schedule this node in */ char **link_groups; /** groups this node is linked to */ @@ -779,6 +785,7 @@ unsigned int sync:1; /**< the sync-groups are active */ unsigned int transport:1; /**< the transport is active */ unsigned int async:1; /**< async processing, one cycle latency */ + unsigned int lazy:1; /**< the graph is lazy scheduling */ uint32_t port_user_data_size; /**< extra size for port user data */
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/proxy.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/proxy.c
Changed
@@ -191,6 +191,9 @@ if (proxy->core) pw_map_remove(&proxy->core->objects, proxy->id); proxy->in_map = false; + + /* Make sure any future method calls fail */ + proxy->id = SPA_ID_INVALID; } }
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/stream.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/stream.c
Changed
@@ -1057,6 +1057,8 @@ if ((b = get_buffer(stream, io->buffer_id)) != NULL) { pw_log_trace_fp("%p: recycle buffer %d", stream, b->id); queue_push(impl, &impl->dequeued, b); + if (impl->early_process) + ask_more = true; } /* pop new buffer */ @@ -2523,6 +2525,12 @@ return stream->node->driving; } +SPA_EXPORT +bool pw_stream_is_lazy(struct pw_stream *stream) +{ + return stream->node->lazy; +} + static int do_trigger_driver(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data)
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/stream.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/stream.h
Changed
@@ -569,16 +569,33 @@ * available (output) or needed (input). Since 0.3.34 */ bool pw_stream_is_driving(struct pw_stream *stream); +/** Check if the graph is using lazy scheduling. If the stream is + * driving according to \ref pw_stream_is_driving(), then it should + * consider taking into account the RequestProcess commands when + * driving the graph. + * + * If the stream is not driving, it should send out RequestProcess + * events with \ref pw_stream_emit_event() or indirectly with + * \ref pw_stream_trigger_process() to suggest a new graph cycle + * to the driver. + * + * It is not a requirement that all RequestProcess events/commands + * need to start a graph cycle. + * Since 1.2.7 */ +bool pw_stream_is_lazy(struct pw_stream *stream); + /** Trigger a push/pull on the stream. One iteration of the graph will - * be scheduled. If it successfully finishes, process() will be called. - * It is possible for the graph iteration to not finish, so + * be scheduled when the stream is driving according to + * \ref pw_stream_is_driving(). If it successfully finishes, process() + * will be called and the trigger_done event will be emitted. It is + * possible for the graph iteration to not finish, so * pw_stream_trigger_process() needs to be called again even if process() - * is not called. + * and trigger_done is not called. * * If there is a deadline after which the stream will have xrun, * pw_stream_trigger_process() should be called then, whether or not - * process() has been called. Sound hardware will xrun if there is - * any delay in audio processing, so the ALSA plugin triggers the + * process()/trigger_done has been called. Sound hardware will xrun if + * there is any delay in audio processing, so the ALSA plugin triggers the * graph every quantum to ensure audio keeps flowing. Drivers that * do not have a deadline, such as the freewheel driver, should * use a timeout to ensure that forward progress keeps being made. @@ -586,6 +603,13 @@ * the graph is taking 3x longer than normal, it is likely that it * is hung and should be retriggered. * + * Streams that are not drivers according to \ref pw_stream_is_driving() + * can also call this method. The result is that a RequestProcess event + * is sent to the driver. If the graph is lazy scheduling according to + * \ref pw_stream_is_lazy(), this might result in a graph cycle by the + * driver. If the graph is not lazy scheduling and the stream is not a + * driver, this method will have no effect. + * * Since 0.3.34 */ int pw_stream_trigger_process(struct pw_stream *stream);
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/tools/pw-dot.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/tools/pw-dot.c
Changed
@@ -376,10 +376,10 @@ dot_data_add_string(dd, "\\loutput_node_id: "); dot_data_add_uint32(dd, info->output_node_id); dot_data_add_string(dd, "\\linput_node_id: "); - dot_data_add_uint32(dd, info->output_node_id); + dot_data_add_uint32(dd, info->input_node_id); dot_data_add_string(dd, "\\loutput_port_id: "); dot_data_add_uint32(dd, info->output_port_id); - dot_data_add_string(dd, "\\linput_node_id: "); + dot_data_add_string(dd, "\\linput_port_id: "); dot_data_add_uint32(dd, info->input_port_id); dot_data_add_string(dd, "\\lstate: "); dot_data_add_string_escaped(dd, pw_link_state_as_string(info->state));
View file
_service:download_url:pipewire-1.2.6.tar.bz2/src/tools/pw-dump.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/tools/pw-dump.c
Changed
@@ -1396,7 +1396,7 @@ if ((o = find_object(d, id)) == NULL) return; - if (!d->pattern || object_matches(o, d->pattern)) { + if (d->monitor && (!d->pattern || object_matches(o, d->pattern))) { d->state = STATE_FIRST; if (d->state == STATE_FIRST) put_begin(d, NULL, "", 0);
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.