summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.dev>2022-06-16 03:12:44 +0200
committerNiklas Haas <github-daiK1o@haasn.dev>2022-09-02 01:27:31 +0200
commit9be52e5dd8d5b4ae56dfd68430191c818f646beb (patch)
treef341b8121532e07205c4da16a9d4312c4669aeda /audio
parent04062b6f897960938649047c3e2c5ceb08bae295 (diff)
downloadmpv-9be52e5dd8d5b4ae56dfd68430191c818f646beb.tar.bz2
mpv-9be52e5dd8d5b4ae56dfd68430191c818f646beb.tar.xz
ad_lavc: strip non-normalized floats
`opus` codec likes returning denormalized floats in some cases, causing wacky issues. Fixes #10290
Diffstat (limited to 'audio')
-rw-r--r--audio/aframe.c31
-rw-r--r--audio/aframe.h1
-rw-r--r--audio/decode/ad_lavc.c3
3 files changed, 35 insertions, 0 deletions
diff --git a/audio/aframe.c b/audio/aframe.c
index 6781bb7b55..9b0827f64c 100644
--- a/audio/aframe.c
+++ b/audio/aframe.c
@@ -466,6 +466,37 @@ void mp_aframe_skip_samples(struct mp_aframe *f, int samples)
f->pts += samples / mp_aframe_get_effective_rate(f);
}
+// sanitize a floating point sample value
+#define sanitizef(f) do { \
+ if (!isnormal(f)) \
+ (f) = 0; \
+} while (0)
+
+void mp_aframe_sanitize_float(struct mp_aframe *mpa)
+{
+ int format = af_fmt_from_planar(mp_aframe_get_format(mpa));
+ if (format != AF_FORMAT_FLOAT && format != AF_FORMAT_DOUBLE)
+ return;
+ int num_planes = mp_aframe_get_planes(mpa);
+ uint8_t **planes = mp_aframe_get_data_rw(mpa);
+ if (!planes)
+ return;
+ for (int p = 0; p < num_planes; p++) {
+ void *ptr = planes[p];
+ int total = mp_aframe_get_total_plane_samples(mpa);
+ switch (format) {
+ case AF_FORMAT_FLOAT:
+ for (int s = 0; s < total; s++)
+ sanitizef(((float *)ptr)[s]);
+ break;
+ case AF_FORMAT_DOUBLE:
+ for (int s = 0; s < total; s++)
+ sanitizef(((double *)ptr)[s]);
+ break;
+ }
+ }
+}
+
// Return the timestamp of the sample just after the end of this frame.
double mp_aframe_end_pts(struct mp_aframe *f)
{
diff --git a/audio/aframe.h b/audio/aframe.h
index be456a3dd1..d19c7e8bcb 100644
--- a/audio/aframe.h
+++ b/audio/aframe.h
@@ -60,6 +60,7 @@ char *mp_aframe_format_str_buf(char *buf, size_t buf_size, struct mp_aframe *fmt
#define mp_aframe_format_str(fmt) mp_aframe_format_str_buf((char[32]){0}, 32, (fmt))
void mp_aframe_skip_samples(struct mp_aframe *f, int samples);
+void mp_aframe_sanitize_float(struct mp_aframe *f);
double mp_aframe_end_pts(struct mp_aframe *f);
double mp_aframe_duration(struct mp_aframe *f);
void mp_aframe_clip_timestamps(struct mp_aframe *f, double start, double end);
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index 34c3a183eb..6ae7d80bf5 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -260,6 +260,9 @@ static int receive_frame(struct mp_filter *da, struct mp_frame *out)
priv->trim_samples -= trim;
}
+ // Strip possibly bogus float values like Infinity, NaN, denormalized
+ mp_aframe_sanitize_float(mpframe);
+
if (mp_aframe_get_size(mpframe) > 0) {
*out = MAKE_FRAME(MP_FRAME_AUDIO, mpframe);
} else {