ad_lavc: strip non-normalized floats

`opus` codec likes returning denormalized floats in some cases, causing
wacky issues.

Fixes #10290
This commit is contained in:
Niklas Haas 2022-06-16 03:12:44 +02:00 committed by Niklas Haas
parent 04062b6f89
commit 9be52e5dd8
3 changed files with 35 additions and 0 deletions

View File

@ -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)
{

View File

@ -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);

View File

@ -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 {