Compare commits

...

13 commits

Author SHA1 Message Date
Arun Raghavan
8f839526a5 Update NEWS for 16.2 2024-11-01 22:13:42 -04:00
flyingOwl
566849c4af time-smoother-2: Fix time calculation by comparing timestamps
This fixes the rare case of resume_time being bigger than time_stamp. Which
happens sometimes when a gstreamer client is quickly seeking through a
media file. The resulting integer underflow then causes a huge value in
current_time which will break the playback.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/764>
2024-09-17 08:40:56 -04:00
Arun Raghavan
0647fcb622 tests: Don't run volume tests with impossible alignments
This worked so far somehow, but we were sending in some samples at
unrealistic alignments (given that pa_memblockq will be frame-aligned,
and we expect all operations to occur per-frame as well).

Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/3803
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/812>
2024-09-13 12:38:21 -04:00
Igor V. Kovalenko
9a428e4c50 Fix crash running in restricted environment.
When `pwd.h` header is not available (i.e. not using glibc) and environment
variables are not set (e.g. running via `env --ignore-environment`) client
library would crash due to uninitialized variable in `pa_get_home_dir()`.
Add missing initialization to fix that.

Fixes: #3792
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/800>
2024-09-13 12:38:21 -04:00
Igor V. Kovalenko
a8b28d86cd shell-completion: Fix typo in --use-pid-file= suggestion
Fixes #3786

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/799>
2024-09-13 12:38:21 -04:00
Igor V. Kovalenko
f2836dc6b6 rtp: Accept CRLF delimiters in SDP as required by RFC 4566
RFC 4566 states that SDP record is terminated with CRLF, and parsers should be
able to accept records terminated with just LF. Pulseaudio only accepts LF here.

Fix this by accepting both CRLF and LF terminators.
2024-09-13 12:38:21 -04:00
Georg Chini
686ae9c696 time-smoother-2: Fix stream time when stream starts paused
When a stream is started but has not yet called smoother_2_put(), pa_smoother_2_get()
returns the time since the start of the stream even if the stream was started paused.
When the stream is started paused, pa_smoother_2_get() should return 0 instead. This
patch fixes the problem.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/745>
2024-09-13 12:33:02 -04:00
Tanu Kaskinen
e5ad31e873 Update NEWS for 16.1
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/727>
2022-06-21 13:54:48 +03:00
Jan Palus
e4d54dae91 bluetooth/gst: Correct var type for GST_TYPE_BITMASK
GST_TYPE_BITMASK is 64-bit bit mask while corresponding channel_mask in
pulseaudio is int therefore usually 32-bit. Switch to uint64_t instead
to match internal representation in gstreamer.

Fixes pulseaudio crash on ARM 32-bit when pulseaudio is compiled with
gstreamer and either LDAC or aptX support is available.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/723>
2022-06-20 14:02:29 +03:00
Georg Chini
0e896eb518 combine-sink: Fix threading issue during underrun
A recent commit added i->origin sink for the sink inputs of the combine sinks.
Therefore pa_sink_process_input_underruns() treated the combine sink like
filter sinks. pa_sink_process_input_underruns() calls itself with the
origin sink, which is only correct for filter sinks because they run in the
thread context of the origin sink. The combine sink however has its own
thread context, so pa_sink_process_input_underruns() was executed in the
wrong context.
This patch fixes the issue by skipping the section for module-combine-sink.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/722>
2022-06-20 14:02:15 +03:00
Igor V. Kovalenko
ca8c5242eb rtp: Initialize SDP info struct field added for OPUS
Turned out that pa_sdp_info::enable_opus is never initialized, which seldom
makes module-rtp-recv believe it will be playing OPUS-encoded stream even though
discovered SDP record does not indicate OPUS codec in metadata.

Fix this by adding missing initializer.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/720>
2022-06-20 14:01:56 +03:00
Jaechul Lee
437cfe4630 sound-file-stream: Fix crash when playing a file which is not aligned
pulseaudio crash occurred when I play a file using pacmd play-file command.
The file is not aligned with its frame size and the last rendering size
is also not aligned. Thus, an assertion was generated at the end of the
file as the following.

memblockq.c: Assertion 'uchunk->length % bq->base == 0' failed at
../src/pulsecore/memblockq.c:288, function pa_memblockq_push(). Aborting.

When I play the file using paplay, it works good. So, I changed to
pa_memblockq_push_align instead of pa_memblockq_push to prevent the
assertion.

Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/717>
2022-06-20 14:01:47 +03:00
Sean Greenslade
8299a7f100 pactl: fix parsing of percentages with decimal points
The logic for detecting which type of volume was given incorrectly interpreted
any value with a decimal as a VOL_LINEAR. It also could set multiple flags,
which would put the flags variable into an indeterminate state. Additionally,
the flags stack variable was uninitialized which could also lead to an
indeterminate flag state.

Percentages are now prioritized over all other types, and only one type flag
can be set.
2022-06-20 14:01:26 +03:00
12 changed files with 115 additions and 45 deletions

36
NEWS
View file

@ -1,3 +1,39 @@
PulseAudio 16.2
A bug fix release.
* A couple of time-smoother-2 fixes, mainly manifesting in issues for GStreamer clients
* Fix a crash in some restricted environments
* Minor RTP spec compliance fix
* Minur completion and tests fixups
Contributors
Arun Raghavan
Georg Chini
Igor V. Kovalenko
flyingOwl
PulseAudio 16.1
A bug fix release.
* Fix parsing of percentage volumes with decimal points in pactl
* Fix crash with the "pacmd play-file" command when reads from the disk aren't frame-aligned
* Fix module-rtp-recv sometimes thinking it's receiving an Opus stream when it's not
* Fix frequent crashing in module-combine-sink, regression in 16.0
* Fix crashing on 32-bit architectures when using the GStreamer codecs for LDAC and AptX
Contributors
Georg Chini
Igor V. Kovalenko
Jaechul Lee
Jan Palus
Sean Greenslade
PulseAudio 16.0
Changes at a glance:

View file

@ -500,7 +500,7 @@ _pulseaudio()
--start -k --kill --check --system= -D --daemonize= --fail= --high-priority=
--realtime= --disallow-module-loading= --disallow-exit= --exit-idle-time=
--scache-idle-time= --log-level= -v --log-target= --log-meta= --log-time=
--log-backtrace= -p --dl-search-path= --resample-method= --use-pit-file=
--log-backtrace= -p --dl-search-path= --resample-method= --use-pid-file=
--no-cpu-limit= --disable-shm= --enable-memfd= -L --load= -F --file= -C -n'
_init_completion -n = || return

View file

@ -22,6 +22,7 @@
#endif
#include <arpa/inet.h>
#include <stdint.h>
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
@ -82,7 +83,7 @@ fail:
static GstCaps *gst_create_caps_from_sample_spec(const pa_sample_spec *ss) {
gchar *sample_format;
GstCaps *caps;
int channel_mask;
uint64_t channel_mask;
switch (ss->format) {
case PA_SAMPLE_S16LE:

View file

@ -213,7 +213,9 @@ int pa_sap_recv(pa_sap_context *c, bool *goodbye) {
if ((unsigned) size >= sizeof(MIME_TYPE) && pa_streq(e, MIME_TYPE)) {
e += sizeof(MIME_TYPE);
size -= (int) sizeof(MIME_TYPE);
} else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)) {
} else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)
|| strcspn(e, "\r\n") != sizeof(PA_SDP_HEADER)-1) {
/* SDP header does not start with v=0[\r]\n */
pa_log_warn("Invalid SDP header.");
goto fail;
}

View file

@ -73,7 +73,7 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u
pa_assert_se(inet_ntop(af, dst, buf_dst, sizeof(buf_dst)));
return pa_sprintf_malloc(
PA_SDP_HEADER
PA_SDP_HEADER "\n"
"o=%s %lu 0 IN %s %s\n"
"s=%s\n"
"c=IN %s %s\n"
@ -129,18 +129,31 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) {
i->origin = i->session_name = NULL;
i->salen = 0;
i->payload = 255;
i->enable_opus = false;
if (!pa_startswith(t, PA_SDP_HEADER)) {
if (pa_startswith(t, PA_SDP_HEADER)) {
t += sizeof(PA_SDP_HEADER) - 1;
/* CR delimiter is optional */
if (*t == '\r')
t++;
/* LF delimiter is mandatory */
if (*t == '\n')
t++;
else {
pa_log("Failed to parse SDP data: missing header record terminator LF.");
goto fail;
}
} else {
pa_log("Failed to parse SDP data: invalid header.");
goto fail;
}
t += sizeof(PA_SDP_HEADER)-1;
while (*t) {
size_t l;
l = strcspn(t, "\n");
l = strcspn(t, "\r\n");
if (l <= 2) {
pa_log("Failed to parse SDP data: line too short: >%s<.", t);
@ -240,8 +253,17 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) {
t += l;
/* CR delimiter is optional */
if (*t == '\r')
t++;
/* LF delimiter is mandatory */
if (*t == '\n')
t++;
else {
pa_log("Failed to parse SDP data: missing record terminator LF.");
goto fail;
}
}
if (!i->origin || (!is_goodbye && (!i->salen || i->payload > 127 || !ss_valid || port == 0))) {

View file

@ -26,7 +26,7 @@
#include <pulse/sample.h>
#define PA_SDP_HEADER "v=0\n"
#define PA_SDP_HEADER "v=0"
typedef struct pa_sdp_info {
char *origin;

View file

@ -167,7 +167,7 @@ char *pa_get_host_name(char *s, size_t l) {
char *pa_get_home_dir(char *s, size_t l) {
char *e;
char *dir;
char *dir = NULL;
#ifdef HAVE_PWD_H
struct passwd *r;
#endif

View file

@ -1016,20 +1016,29 @@ size_t pa_sink_process_input_underruns(pa_sink *s, size_t left_to_play) {
if (i->origin_sink) {
size_t filter_result, left_to_play_origin;
/* The recursive call works in the origin sink domain ... */
left_to_play_origin = pa_convert_size(left_to_play, &i->sink->sample_spec, &i->origin_sink->sample_spec);
/* The combine sink sets i->origin sink but has a different threading model
* than the filter sinks. Therefore the recursion below may not be executed
* because pa_sink_process_input_underruns() was not called in the thread
* context of the origin sink.
* FIXME: It is unclear if some other kind of recursion would be necessary
* for the combine sink. */
if (!i->module || !pa_safe_streq(i->module->name, "module-combine-sink")) {
/* .. and returns the time to sleep before waking up. We need the
* underrun duration for comparisons, so we undo the subtraction on
* the return value... */
filter_result = left_to_play_origin - pa_sink_process_input_underruns(i->origin_sink, left_to_play_origin);
/* The recursive call works in the origin sink domain ... */
left_to_play_origin = pa_convert_size(left_to_play, &i->sink->sample_spec, &i->origin_sink->sample_spec);
/* ... and convert it back to the master sink domain */
filter_result = pa_convert_size(filter_result, &i->origin_sink->sample_spec, &i->sink->sample_spec);
/* .. and returns the time to sleep before waking up. We need the
* underrun duration for comparisons, so we undo the subtraction on
* the return value... */
filter_result = left_to_play_origin - pa_sink_process_input_underruns(i->origin_sink, left_to_play_origin);
/* Remember the longest underrun so far */
if (filter_result > result)
result = filter_result;
/* ... and convert it back to the master sink domain */
filter_result = pa_convert_size(filter_result, &i->origin_sink->sample_spec, &i->sink->sample_spec);
/* Remember the longest underrun so far */
if (filter_result > result)
result = filter_result;
}
}
if (uf == 0) {

View file

@ -185,7 +185,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
tchunk.length = (size_t) n * fs;
pa_memblockq_push(u->memblockq, &tchunk);
pa_memblockq_push_align(u->memblockq, &tchunk);
pa_memblock_unref(tchunk.memblock);
}

View file

@ -295,7 +295,7 @@ pa_usec_t pa_smoother_2_get(pa_smoother_2 *s, pa_usec_t time_stamp) {
/* If the smoother has not started, just return system time since resume */
if (!s->start_time) {
if (time_stamp >= s->resume_time)
if (time_stamp >= s->resume_time && !s->paused)
current_time = time_stamp - s->resume_time;
else
current_time = 0;
@ -307,7 +307,8 @@ pa_usec_t pa_smoother_2_get(pa_smoother_2 *s, pa_usec_t time_stamp) {
/* If we are initializing, add the time since resume to the card time at pause_time */
else if (s->init) {
current_time += (s->pause_time - s->start_time - s->time_offset - s->fixup_time) * s->time_factor;
current_time += (time_stamp - s->resume_time) * s->time_factor;
if (time_stamp > s->resume_time)
current_time += (time_stamp - s->resume_time) * s->time_factor;
/* Smoother is running, calculate current sound card time */
} else

View file

@ -43,6 +43,7 @@ static void run_volume_test(
int channels,
bool correct,
bool perf) {
fail_unless(align % channels == 0);
PA_DECLARE_ALIGNED(8, int16_t, s[SAMPLES]) = { 0 };
PA_DECLARE_ALIGNED(8, int16_t, s_ref[SAMPLES]) = { 0 };
@ -56,8 +57,6 @@ static void run_volume_test(
samples_ref = s_ref + (8 - align);
samples_orig = s_orig + (8 - align);
nsamples = SAMPLES - (8 - align);
if (nsamples % channels)
nsamples -= nsamples % channels;
size = nsamples * sizeof(int16_t);
pa_random(samples, size);
@ -119,12 +118,12 @@ START_TEST (svolume_mmx_test) {
pa_log_debug("Checking MMX svolume");
for (i = 1; i <= 3; i++) {
for (j = 0; j < 7; j++)
run_volume_test(mmx_func, orig_func, j, i, true, false);
for (j = 0; j <= 7; j += i)
run_volume_test(mmx_func, orig_func, j, i, true, j == 0);
}
run_volume_test(mmx_func, orig_func, 7, 1, true, true);
run_volume_test(mmx_func, orig_func, 7, 2, true, true);
run_volume_test(mmx_func, orig_func, 7, 3, true, true);
run_volume_test(mmx_func, orig_func, 6, 2, true, true);
run_volume_test(mmx_func, orig_func, 6, 3, true, true);
}
END_TEST
@ -146,12 +145,12 @@ START_TEST (svolume_sse_test) {
pa_log_debug("Checking SSE2 svolume");
for (i = 1; i <= 3; i++) {
for (j = 0; j < 7; j++)
run_volume_test(sse_func, orig_func, j, i, true, false);
for (j = 0; j < 7; j += i)
run_volume_test(sse_func, orig_func, j, i, true, j == 0);
}
run_volume_test(sse_func, orig_func, 7, 1, true, true);
run_volume_test(sse_func, orig_func, 7, 2, true, true);
run_volume_test(sse_func, orig_func, 7, 3, true, true);
run_volume_test(sse_func, orig_func, 6, 2, true, true);
run_volume_test(sse_func, orig_func, 6, 3, true, true);
}
END_TEST
#endif /* defined (__i386__) || defined (__amd64__) */
@ -175,12 +174,12 @@ START_TEST (svolume_arm_test) {
pa_log_debug("Checking ARM svolume");
for (i = 1; i <= 3; i++) {
for (j = 0; j < 7; j++)
run_volume_test(arm_func, orig_func, j, i, true, false);
for (j = 0; j < 7; j += i)
run_volume_test(arm_func, orig_func, j, i, true, j == 0);
}
run_volume_test(arm_func, orig_func, 7, 1, true, true);
run_volume_test(arm_func, orig_func, 7, 2, true, true);
run_volume_test(arm_func, orig_func, 7, 3, true, true);
run_volume_test(arm_func, orig_func, 6, 2, true, true);
run_volume_test(arm_func, orig_func, 6, 3, true, true);
}
END_TEST
#endif /* defined (__arm__) && defined (__linux__) */
@ -207,11 +206,11 @@ START_TEST (svolume_orc_test) {
pa_log_debug("Checking Orc svolume");
for (i = 1; i <= 2; i++) {
for (j = 0; j < 7; j++)
run_volume_test(orc_func, orig_func, j, i, true, false);
for (j = 0; j < 7; j += i)
run_volume_test(orc_func, orig_func, j, i, true, j == 0);
}
run_volume_test(orc_func, orig_func, 7, 1, true, true);
run_volume_test(orc_func, orig_func, 7, 2, true, true);
run_volume_test(orc_func, orig_func, 6, 2, true, true);
}
END_TEST

View file

@ -2527,16 +2527,16 @@ static int parse_volume(const char *vol_spec, pa_volume_t *vol, enum volume_flag
vs = pa_xstrdup(vol_spec);
*vol_flags = (pa_startswith(vs, "+") || pa_startswith(vs, "-")) ? VOL_RELATIVE : VOL_ABSOLUTE;
if (strchr(vs, '.'))
*vol_flags |= VOL_LINEAR;
if (pa_endswith(vs, "%")) {
*vol_flags |= VOL_PERCENT;
vs[strlen(vs)-1] = 0;
}
if (pa_endswith(vs, "db") || pa_endswith(vs, "dB")) {
else if (pa_endswith(vs, "db") || pa_endswith(vs, "dB")) {
*vol_flags |= VOL_DECIBEL;
vs[strlen(vs)-2] = 0;
}
else if (strchr(vs, '.'))
*vol_flags |= VOL_LINEAR;
atod_input = vs;
@ -2597,7 +2597,7 @@ static int parse_volumes(char *args[], unsigned n) {
volume.channels = n;
for (i = 0; i < volume.channels; i++) {
enum volume_flags flags;
enum volume_flags flags = 0;
if (parse_volume(args[i], &volume.values[i], &flags) < 0)
return -1;