Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
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;
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
.