summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/filter/af.c185
-rw-r--r--audio/filter/af.h5
-rw-r--r--audio/filter/af_lavrresample.c21
3 files changed, 62 insertions, 149 deletions
diff --git a/audio/filter/af.c b/audio/filter/af.c
index 21b0982692..657340e252 100644
--- a/audio/filter/af.c
+++ b/audio/filter/af.c
@@ -266,101 +266,77 @@ static void af_print_filter_chain(struct af_stream *s, struct af_instance *at,
MP_MSG(s, msg_level, " [ao] %s\n", mp_audio_config_to_str(&s->output));
}
-// in is what af can take as input - insert a conversion filter if the actual
-// input format doesn't match what af expects.
-// Returns:
-// AF_OK: must call af_reinit() or equivalent, format matches (or is closer)
-// AF_FALSE: nothing was changed, format matches
-// else: error
-static int af_fix_format_conversion(struct af_stream *s,
- struct af_instance **p_af,
- struct mp_audio in)
-{
- int rv;
- struct af_instance *af = *p_af;
- struct af_instance *prev = af->prev;
- struct mp_audio actual = *prev->data;
- if (actual.format == in.format)
- return AF_FALSE;
- int dstfmt = in.format;
- char *filter = "lavrresample";
- if (!af_lavrresample_test_conversion(actual.format, dstfmt))
- return AF_ERROR;
- if (strcmp(filter, prev->info->name) == 0) {
- if (prev->control(prev, AF_CONTROL_SET_FORMAT, &dstfmt) == AF_OK) {
- *p_af = prev;
- return AF_OK;
- }
- return AF_ERROR;
- }
- struct af_instance *new = af_prepend(s, af, filter, NULL);
- if (new == NULL)
- return AF_ERROR;
- new->auto_inserted = true;
- if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_FORMAT, &dstfmt))) {
- af_remove(s, new);
- return rv;
+static void reset_formats(struct af_stream *s)
+{
+ struct mp_audio none = {0};
+ for (struct af_instance *af = s->first; af; af = af->next) {
+ if (af != s->first && af != s->last)
+ mp_audio_copy_config(af->data, &none);
}
- *p_af = new;
- return AF_OK;
}
-// same as af_fix_format_conversion - only wrt. channels
-static int af_fix_channels(struct af_stream *s, struct af_instance **p_af,
- struct mp_audio in)
+static int filter_reinit(struct af_instance *af)
{
- int rv;
- struct af_instance *af = *p_af;
struct af_instance *prev = af->prev;
- struct mp_audio actual = *prev->data;
- if (mp_chmap_equals(&actual.channels, &in.channels))
- return AF_FALSE;
- if (prev->control(prev, AF_CONTROL_SET_CHANNELS, &in.channels) == AF_OK) {
- *p_af = prev;
- return AF_OK;
- }
- char *filter = "lavrresample";
- struct af_instance *new = af_prepend(s, af, filter, NULL);
- if (new == NULL)
+ assert(prev);
+
+ // Check if this is the first filter
+ struct mp_audio in = *prev->data;
+ // Reset just in case...
+ mp_audio_set_null_data(&in);
+
+ if (!mp_audio_config_valid(&in))
return AF_ERROR;
- new->auto_inserted = true;
- if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_CHANNELS, &in.channels)))
- return rv;
- *p_af = new;
- return AF_OK;
-}
-static int af_fix_rate(struct af_stream *s, struct af_instance **p_af,
- struct mp_audio in)
-{
- int rv;
- struct af_instance *af = *p_af;
- struct af_instance *prev = af->prev;
- struct mp_audio actual = *prev->data;
- if (actual.rate == in.rate)
- return AF_FALSE;
- if (prev->control(prev, AF_CONTROL_SET_RESAMPLE_RATE, &in.rate) == AF_OK) {
- *p_af = prev;
- return AF_OK;
+ af->fmt_in = in;
+ int rv = af->control(af, AF_CONTROL_REINIT, &in);
+ if (rv == AF_OK && !mp_audio_config_equals(&in, prev->data))
+ rv = AF_FALSE; // conversion filter needed
+ if (rv == AF_FALSE)
+ af->fmt_in = in;
+
+ if (rv == AF_OK) {
+ if (!mp_audio_config_valid(af->data))
+ return AF_ERROR;
+ af->fmt_out = *af->data;
}
- char *filter = "lavrresample";
- struct af_instance *new = af_prepend(s, af, filter, NULL);
- if (new == NULL)
- return AF_ERROR;
- new->auto_inserted = true;
- if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_RESAMPLE_RATE, &in.rate)))
- return rv;
- *p_af = new;
- return AF_OK;
+
+ return rv;
}
-static void reset_formats(struct af_stream *s)
+static int filter_reinit_with_conversion(struct af_stream *s, struct af_instance *af)
{
- for (struct af_instance *af = s->first; af; af = af->next) {
- af->control(af, AF_CONTROL_SET_RESAMPLE_RATE, &(int){0});
- af->control(af, AF_CONTROL_SET_CHANNELS, &(struct mp_chmap){0});
- af->control(af, AF_CONTROL_SET_FORMAT, &(int){0});
+ int rv = filter_reinit(af);
+
+ // Conversion filter is needed
+ if (rv == AF_FALSE) {
+ // First try if we can change the output format of the previous
+ // filter to the input format the current filter is expecting.
+ struct mp_audio in = af->fmt_in;
+ if (af->prev != s->first && !mp_audio_config_equals(af->data, &in)) {
+ // This should have been successful (because it succeeded
+ // before), even if just reverting to the old output format.
+ mp_audio_copy_config(af->data, &in);
+ if (filter_reinit(af->prev) != AF_OK)
+ return AF_ERROR;
+ }
+ if (!mp_audio_config_equals(af->prev->data, &in)) {
+ // Retry with conversion filter added.
+ struct af_instance *new =
+ af_prepend(s, af, "lavrresample", NULL);
+ if (!new)
+ return AF_ERROR;
+ new->auto_inserted = true;
+ mp_audio_copy_config(new->data, &in);
+ rv = filter_reinit(new);
+ if (rv != AF_OK)
+ af_remove(s, new);
+ }
+ if (rv == AF_OK)
+ rv = filter_reinit(af);
}
+
+ return rv;
}
// Return AF_OK on success or AF_ERROR on failure.
@@ -378,52 +354,18 @@ static int af_reinit(struct af_stream *s)
// Start with the second filter, as the first filter is the special input
// filter which needs no initialization.
struct af_instance *af = s->first->next;
- // Up to 4 retries per filter (channel, rate, format conversions)
- int max_retry = 4;
- int retry = 0;
while (af) {
- if (retry >= max_retry)
- goto negotiate_error;
-
- // Check if this is the first filter
- struct mp_audio in = *af->prev->data;
- // Reset just in case...
- mp_audio_set_null_data(&in);
-
- if (!mp_audio_config_valid(&in))
- goto error;
+ int rv = filter_reinit_with_conversion(s, af);
- af->fmt_in = in;
- int rv = af->control(af, AF_CONTROL_REINIT, &in);
- if (rv == AF_OK && !mp_audio_config_equals(&in, af->prev->data))
- rv = AF_FALSE; // conversion filter needed
switch (rv) {
case AF_OK:
- if (!mp_audio_config_valid(af->data))
- goto error;
- af->fmt_out = *af->data;
af = af->next;
break;
- case AF_FALSE: { // Configuration filter is needed
- if (af_fix_channels(s, &af, in) == AF_OK) {
- retry++;
- continue;
- }
- if (af_fix_rate(s, &af, in) == AF_OK) {
- retry++;
- continue;
- }
- // Do this last, to prevent "format->lavrresample" being added to
- // the filter chain when output formats not supported by
- // af_lavrresample are in use.
- if (af_fix_format_conversion(s, &af, in) == AF_OK) {
- retry++;
- continue;
- }
+ case AF_FALSE: {
// If the format conversion is (probably) caused by spdif, then
// (as a feature) drop the filter, instead of failing hard.
int fmt_in1 = af->prev->data->format;
- int fmt_in2 = in.format;
+ int fmt_in2 = af->fmt_in.format;
if (af_fmt_is_valid(fmt_in1) && af_fmt_is_valid(fmt_in2)) {
bool spd1 = af_fmt_is_spdif(fmt_in1);
bool spd2 = af_fmt_is_spdif(fmt_in2);
@@ -434,7 +376,6 @@ static int af_reinit(struct af_stream *s)
struct af_instance *aft = af->prev;
af_remove(s, af);
af = aft->next;
- retry++;
continue;
}
}
@@ -452,8 +393,6 @@ static int af_reinit(struct af_stream *s)
af->info->name, rv);
goto error;
}
- if (af && !af->auto_inserted)
- retry = 0;
}
/* Set previously unset fields in s->output to those of the filter chain
diff --git a/audio/filter/af.h b/audio/filter/af.h
index 9c49081f66..697024b781 100644
--- a/audio/filter/af.h
+++ b/audio/filter/af.h
@@ -112,9 +112,6 @@ struct af_stream {
enum af_control {
AF_CONTROL_REINIT = 1,
AF_CONTROL_RESET,
- AF_CONTROL_SET_RESAMPLE_RATE,
- AF_CONTROL_SET_FORMAT,
- AF_CONTROL_SET_CHANNELS,
AF_CONTROL_SET_VOLUME,
AF_CONTROL_GET_VOLUME,
AF_CONTROL_SET_PAN_LEVEL,
@@ -160,6 +157,4 @@ int af_test_output(struct af_instance *af, struct mp_audio *out);
int af_from_ms(int n, float *in, int *out, int rate, float mi, float ma);
float af_softclip(float a);
-bool af_lavrresample_test_conversion(int src_format, int dst_format);
-
#endif /* MPLAYER_AF_H */
diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c
index 6fbb445563..fdef69a16b 100644
--- a/audio/filter/af_lavrresample.c
+++ b/audio/filter/af_lavrresample.c
@@ -173,12 +173,6 @@ static int check_output_conversion(int mp_format)
return af_to_avformat(mp_format);
}
-bool af_lavrresample_test_conversion(int src_format, int dst_format)
-{
- return af_to_avformat(src_format) != AV_SAMPLE_FMT_NONE &&
- check_output_conversion(dst_format) != AV_SAMPLE_FMT_NONE;
-}
-
static struct mp_chmap fudge_pairs[][2] = {
{MP_CHMAP2(BL, BR), MP_CHMAP2(SL, SR)},
{MP_CHMAP2(SL, SR), MP_CHMAP2(BL, BR)},
@@ -407,21 +401,6 @@ static int control(struct af_instance *af, int cmd, void *arg)
r = configure_lavrr(af, in, out, true);
return r;
}
- case AF_CONTROL_SET_FORMAT: {
- int format = *(int *)arg;
- if (format && check_output_conversion(format) == AV_SAMPLE_FMT_NONE)
- return AF_FALSE;
-
- mp_audio_set_format(af->data, format);
- return AF_OK;
- }
- case AF_CONTROL_SET_CHANNELS: {
- mp_audio_set_channels(af->data, (struct mp_chmap *)arg);
- return AF_OK;
- }
- case AF_CONTROL_SET_RESAMPLE_RATE:
- af->data->rate = *(int *)arg;
- return AF_OK;
case AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE: {
s->playback_speed = *(double *)arg;
return AF_OK;