The EBU R128 filter measures the signal and generates LUFS control
notifications for further processing.
It also adds a plugin that can convert LUFS to a gain (based on a target
LUFS).
Also add an example filter-chain to enable the EBU R128 measurement and
how to use the results to adjust the volume dynamically.
See #2286#222#2210
When calculating the adjusted max quantum based off of max_latency, the
first multiplication can overflow uint32_t, leading to the quantum being
wrongfully clamped down.
Signed-off-by: Martin Louazel <martin.louazel@streamunlimited.com>
We increment the refcount of the loop when we hand it out. We use this
refcount to do some load balancing. In some cases we also decrease the
refcount again when the release_loop() functions is called but we only do
this in some modules. The result is that in most cases the refcount
just keeps on going up and this is misleading.
Change the refcount to a last_used timestamp and prefer to use loops
that have not been used in a while.
Fixes#4436
When not using PTP as the driver, it is possible that packet receive and
the process() callback are out of sync, meaning that the target buffer
fill level might be off by upto one ptime's worth of samples
occasionally. This would make the DLL hunt for the target rate, and
cause a constantly varying delay.
Accounting for the delta between the packet receive time and the
process() time allows us to eliminate this jitter, resulting in much
more consistent rate matching.
Use the pipewire ticks again as the clock source.
This was disabled because the v4l2 sources created bad ticks for the
graph. Now that this is improved we can enable the ticks again.
This has the advantage that simple audio playback does not drift
anymore. The only remaining problem would be timestamp drift or
discontinuities, which we don't handle here yet.
Some clocks (v4l2) don't process exactly process buffers at the given
rate/duration so mark this in the clock flags.
We need to use the nsec field in the clock to derive ticks in pw-stream
in that case to get a good clock.
Remove the check for the target rate and duration. The drivers are
supposed to update that now.
The check is a little racy because a new target could have been
configured right after the driver emitted the ready signal. In that
case we should not update the clock values but let the driver run with
the old values and let the new values become active in the next cycle.
When the driver starts, save all previous node timestamps, not just the
previous signal time.
For async nodes, uses the previous timestamps in the profiler messages
so that we get stats with 1 cycle of delay instead of bogus values
because the node is still processing.
Fixes pw-top for async nodes.
Add a filter-graph info structure with the number of inputs and outputs
in the graph definition.
Use the input/outputs to update the number of channels on the capture and
playback streams when not explicitly given. Also copy over the positions
when they match the other stream and were not explicitly specified.
Fixes#4404
If the peer announces an interlace mode then use it. Otherwise assume
that the video is not interlaced.
This also fixes a problem with caps negotiation:
If downstream reports caps with not fixated interlace mode, e.g.
"interlace-mode=(string){ progressive, interleaved, mixed }"
then without this, the caps handle_format_change() (in the pipewiresrc)
are not fixed and the source waits forever for the negotiation to
finish.
Always listen on the receive socket. Find the stream with the given
stream_name of the packet and create it if it doesn't exist.
Also take the sample-rate, channels and format from the packet
parameters instead of the config.
Fixes#4400
Make SPA plugins from all the filter-graph plugins and use the plugin
loader to load them.
Because they are not in the standard plugin path in development, add
the module dir to the plugin path for now.
Make a plugin structure that is dynamically allocated for each plugin
and pass it around to the descriptor instance structures, so that they
all have access to dsp_ops without sharing a static pointer.
The problem with the static pointer is that the dsp_ops structure is
actually allocated in module-filter-chain's instance structure,
so it always points to the instance of the last filter-chain that was
loaded in the process. When this is unloaded, the other filter-chains
crash.