summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorMartin Herkt <lachs0r@srsfckn.biz>2016-08-15 15:19:29 +0200
committerMartin Herkt <lachs0r@srsfckn.biz>2016-08-15 15:19:29 +0200
commitfd1bc95b4865ff789780c2213eefbdf77f0d4d1f (patch)
tree639e098e46cf1b77ecea7df95d7b968c25e1d0c9 /audio
parent1e00bcc14c9b0d9beb8e152f958fc0db4bc6d31b (diff)
parentd7a7e9a8c861c4a9881fcef5cf69c746742b8b88 (diff)
downloadmpv-fd1bc95b4865ff789780c2213eefbdf77f0d4d1f.tar.bz2
mpv-fd1bc95b4865ff789780c2213eefbdf77f0d4d1f.tar.xz
Merge branch 'master' into release/current
Diffstat (limited to 'audio')
-rw-r--r--audio/audio.c45
-rw-r--r--audio/audio.h1
-rw-r--r--audio/chmap.c38
-rw-r--r--audio/chmap.h3
-rw-r--r--audio/chmap_sel.c13
-rw-r--r--audio/chmap_sel.h2
-rw-r--r--audio/decode/ad_lavc.c4
-rw-r--r--audio/filter/af.c260
-rw-r--r--audio/filter/af.h5
-rw-r--r--audio/filter/af_delay.c194
-rw-r--r--audio/filter/af_format.c16
-rw-r--r--audio/filter/af_lavcac3enc.c46
-rw-r--r--audio/filter/af_lavrresample.c21
-rw-r--r--audio/filter/af_volume.c20
-rw-r--r--audio/mixer.c152
-rw-r--r--audio/mixer.h43
-rw-r--r--audio/out/ao.c36
-rw-r--r--audio/out/ao.h12
-rw-r--r--audio/out/ao_alsa.c77
-rw-r--r--audio/out/ao_coreaudio.c2
-rw-r--r--audio/out/ao_coreaudio_exclusive.c2
-rw-r--r--audio/out/ao_coreaudio_properties.c2
-rw-r--r--audio/out/ao_coreaudio_utils.c2
-rw-r--r--audio/out/ao_lavc.c2
-rw-r--r--audio/out/ao_null.c16
-rw-r--r--audio/out/ao_pulse.c5
-rw-r--r--audio/out/ao_wasapi_utils.c2
-rw-r--r--audio/out/internal.h4
-rw-r--r--audio/out/pull.c8
-rw-r--r--audio/out/push.c6
30 files changed, 362 insertions, 677 deletions
diff --git a/audio/audio.c b/audio/audio.c
index 306401b5a4..502bbf2134 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -138,6 +138,9 @@ static void mp_audio_destructor(void *ptr)
* available on every plane. The previous data is kept (for the smallest
* common number of samples before/after resize).
*
+ * This also makes sure the resulting buffer is writable (even in the case
+ * the buffer has the correct size).
+ *
* mpa->samples is not set or used.
*
* This function is flexible enough to handle format and channel layout
@@ -153,6 +156,12 @@ void mp_audio_realloc(struct mp_audio *mpa, int samples)
int size = get_plane_size(mpa, samples);
if (size < 0)
abort(); // oom or invalid parameters
+ if (!mp_audio_is_writeable(mpa)) {
+ for (int n = 0; n < MP_NUM_CHANNELS; n++) {
+ av_buffer_unref(&mpa->allocated[n]);
+ mpa->planes[n] = NULL;
+ }
+ }
for (int n = 0; n < mpa->num_planes; n++) {
if (!mpa->allocated[n] || size != mpa->allocated[n]->size) {
if (av_buffer_realloc(&mpa->allocated[n], size) < 0)
@@ -171,7 +180,7 @@ void mp_audio_realloc(struct mp_audio *mpa, int samples)
// If the buffer is reallocated, also preallocate.
void mp_audio_realloc_min(struct mp_audio *mpa, int samples)
{
- if (samples > mp_audio_get_allocated_size(mpa)) {
+ if (samples > mp_audio_get_allocated_size(mpa) || !mp_audio_is_writeable(mpa)) {
size_t alloc = ta_calc_prealloc_elems(samples);
if (alloc > INT_MAX)
abort(); // oom
@@ -347,9 +356,9 @@ struct mp_audio *mp_audio_from_avframe(struct AVFrame *avframe)
mp_chmap_from_lavc(&lavc_chmap, avframe->channel_layout);
#if LIBAVUTIL_VERSION_MICRO >= 100
- // FFmpeg being special again
- if (lavc_chmap.num != avframe->channels)
- mp_chmap_from_channels(&lavc_chmap, avframe->channels);
+ // FFmpeg being stupid POS again
+ if (lavc_chmap.num != av_frame_get_channels(avframe))
+ mp_chmap_from_channels(&lavc_chmap, av_frame_get_channels(avframe));
#endif
new->rate = avframe->sample_rate;
@@ -394,12 +403,9 @@ fail:
return NULL;
}
-// Returns NULL on failure. The input is always unreffed.
-struct AVFrame *mp_audio_to_avframe_and_unref(struct mp_audio *frame)
+int mp_audio_to_avframe(struct mp_audio *frame, struct AVFrame *avframe)
{
- struct AVFrame *avframe = av_frame_alloc();
- if (!avframe)
- goto fail;
+ av_frame_unref(avframe);
avframe->nb_samples = frame->samples;
avframe->format = af_to_avformat(frame->format);
@@ -410,8 +416,8 @@ struct AVFrame *mp_audio_to_avframe_and_unref(struct mp_audio *frame)
if (!avframe->channel_layout)
goto fail;
#if LIBAVUTIL_VERSION_MICRO >= 100
- // FFmpeg being a stupid POS (but I respect it)
- avframe->channels = frame->channels.num;
+ // FFmpeg being a stupid POS again
+ av_frame_set_channels(avframe, frame->channels.num);
#endif
avframe->sample_rate = frame->rate;
@@ -457,6 +463,23 @@ struct AVFrame *mp_audio_to_avframe_and_unref(struct mp_audio *frame)
avframe = tmp;
}
+ return 0;
+
+fail:
+ av_frame_unref(avframe);
+ return -1;
+}
+
+// Returns NULL on failure. The input is always unreffed.
+struct AVFrame *mp_audio_to_avframe_and_unref(struct mp_audio *frame)
+{
+ struct AVFrame *avframe = av_frame_alloc();
+ if (!avframe)
+ goto fail;
+
+ if (mp_audio_to_avframe(frame, avframe) < 0)
+ goto fail;
+
talloc_free(frame);
return avframe;
diff --git a/audio/audio.h b/audio/audio.h
index e126e93b66..0f32f080b9 100644
--- a/audio/audio.h
+++ b/audio/audio.h
@@ -81,6 +81,7 @@ int mp_audio_make_writeable(struct mp_audio *data);
struct AVFrame;
struct mp_audio *mp_audio_from_avframe(struct AVFrame *avframe);
struct AVFrame *mp_audio_to_avframe_and_unref(struct mp_audio *frame);
+int mp_audio_to_avframe(struct mp_audio *frame, struct AVFrame *avframe);
struct mp_audio_pool;
struct mp_audio_pool *mp_audio_pool_create(void *ta_parent);
diff --git a/audio/chmap.c b/audio/chmap.c
index 1d4970da6c..bbd3a17404 100644
--- a/audio/chmap.c
+++ b/audio/chmap.c
@@ -230,44 +230,6 @@ void mp_chmap_set_unknown(struct mp_chmap *dst, int num_channels)
}
}
-// Return channel index of the given speaker, or -1.
-static int mp_chmap_find_speaker(const struct mp_chmap *map, int speaker)
-{
- for (int n = 0; n < map->num; n++) {
- if (map->speaker[n] == speaker)
- return n;
- }
- return -1;
-}
-
-static void mp_chmap_remove_speaker(struct mp_chmap *map, int speaker)
-{
- int index = mp_chmap_find_speaker(map, speaker);
- if (index >= 0) {
- for (int n = index; n < map->num - 1; n++)
- map->speaker[n] = map->speaker[n + 1];
- map->num--;
- }
-}
-
-// Some decoders output additional, redundant channels, which are usually
-// useless and will mess up proper audio output channel handling.
-// map: channel map from which the channels should be removed
-// requested: if not NULL, and if it contains any of the "useless" channels,
-// don't remove them (this is for convenience)
-void mp_chmap_remove_useless_channels(struct mp_chmap *map,
- const struct mp_chmap *requested)
-{
- if (requested &&
- mp_chmap_find_speaker(requested, MP_SPEAKER_ID_DL) >= 0)
- return;
-
- if (map->num > 2) {
- mp_chmap_remove_speaker(map, MP_SPEAKER_ID_DL);
- mp_chmap_remove_speaker(map, MP_SPEAKER_ID_DR);
- }
-}
-
// Return the ffmpeg/libav channel layout as in <libavutil/channel_layout.h>.
// Speakers not representable by ffmpeg/libav are dropped.
// Warning: this ignores the order of the channels, and will return a channel
diff --git a/audio/chmap.h b/audio/chmap.h
index aa9b1c5a10..dff69336d6 100644
--- a/audio/chmap.h
+++ b/audio/chmap.h
@@ -109,9 +109,6 @@ void mp_chmap_fill_na(struct mp_chmap *map, int num);
void mp_chmap_from_channels(struct mp_chmap *dst, int num_channels);
void mp_chmap_set_unknown(struct mp_chmap *dst, int num_channels);
-void mp_chmap_remove_useless_channels(struct mp_chmap *map,
- const struct mp_chmap *requested);
-
uint64_t mp_chmap_to_lavc(const struct mp_chmap *src);
uint64_t mp_chmap_to_lavc_unchecked(const struct mp_chmap *src);
void mp_chmap_from_lavc(struct mp_chmap *dst, uint64_t src);
diff --git a/audio/chmap_sel.c b/audio/chmap_sel.c
index 45b696c924..4fb7544f20 100644
--- a/audio/chmap_sel.c
+++ b/audio/chmap_sel.c
@@ -374,3 +374,16 @@ void mp_chmal_sel_log(const struct mp_chmap_sel *s, struct mp_log *log, int lev)
if (s->allow_any)
mp_msg(log, lev, " - anything\n");
}
+
+// Select a channel map from the given list that fits best to c. Don't change
+// *c if there's no match, or the list is empty.
+void mp_chmap_sel_list(struct mp_chmap *c, struct mp_chmap *maps, int num_maps)
+{
+ // This is a separate function to keep messing with mp_chmap_sel internals
+ // within this source file.
+ struct mp_chmap_sel sel = {
+ .chmaps = maps,
+ .num_chmaps = num_maps,
+ };
+ mp_chmap_sel_fallback(&sel, c);
+}
diff --git a/audio/chmap_sel.h b/audio/chmap_sel.h
index 5bd8783b83..4b11557a2b 100644
--- a/audio/chmap_sel.h
+++ b/audio/chmap_sel.h
@@ -47,4 +47,6 @@ bool mp_chmap_sel_get_def(const struct mp_chmap_sel *s, struct mp_chmap *map,
struct mp_log;
void mp_chmal_sel_log(const struct mp_chmap_sel *s, struct mp_log *log, int lev);
+void mp_chmap_sel_list(struct mp_chmap *c, struct mp_chmap *maps, int num_maps);
+
#endif
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index 0316f6b7d1..c785c62c90 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -104,9 +104,9 @@ static int init(struct dec_audio *da, const char *decoder)
lavc_context->codec_type = AVMEDIA_TYPE_AUDIO;
lavc_context->codec_id = lavc_codec->id;
- if (opts->downmix) {
+ if (opts->downmix && mpopts->audio_output_channels.num_chmaps == 1) {
lavc_context->request_channel_layout =
- mp_chmap_to_lavc(&mpopts->audio_output_channels);
+ mp_chmap_to_lavc(&mpopts->audio_output_channels.chmaps[0]);
}
// Always try to set - option only exists for AC3 at the moment
diff --git a/audio/filter/af.c b/audio/filter/af.c
index 21b0982692..a132965295 100644
--- a/audio/filter/af.c
+++ b/audio/filter/af.c
@@ -31,7 +31,6 @@
#include "af.h"
// Static list of filters
-extern const struct af_info af_info_delay;
extern const struct af_info af_info_channels;
extern const struct af_info af_info_format;
extern const struct af_info af_info_volume;
@@ -46,7 +45,6 @@ extern const struct af_info af_info_lavfi;
extern const struct af_info af_info_rubberband;
static const struct af_info *const filter_list[] = {
- &af_info_delay,
&af_info_channels,
&af_info_format,
&af_info_volume,
@@ -256,6 +254,8 @@ static void af_print_filter_chain(struct af_stream *s, struct af_instance *at,
mp_snprintf_cat(b, sizeof(b), "\"%s\" ", af->label);
if (af->data)
mp_snprintf_cat(b, sizeof(b), "%s", mp_audio_config_to_str(af->data));
+ if (af->auto_inserted)
+ mp_snprintf_cat(b, sizeof(b), " [a]");
if (af == at)
mp_snprintf_cat(b, sizeof(b), " <-");
MP_MSG(s, msg_level, "%s\n", b);
@@ -266,164 +266,156 @@ 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)
+static void reset_formats(struct af_stream *s)
{
- 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;
+ 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;
+
+ 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;
+ }
+
+ return rv;
}
-static int af_fix_rate(struct af_stream *s, struct af_instance **p_af,
- struct mp_audio in)
+static int filter_reinit_with_conversion(struct af_stream *s, 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 (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;
+ 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->prev->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->prev->data, &in);
+ rv = filter_reinit(af->prev);
+ if (rv != AF_OK)
+ return rv;
+ }
+ 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);
}
- 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 af_find_output_conversion(struct af_stream *s, struct mp_audio *cfg)
{
- 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});
+ assert(mp_audio_config_valid(&s->output));
+ assert(s->initialized > 0);
+
+ if (mp_chmap_equals_reordered(&s->input.channels, &s->output.channels))
+ return AF_ERROR;
+
+ // Heuristic to detect point of conversion. If it looks like something
+ // more complicated is going on, better bail out.
+ // We expect that the last filter converts channels.
+ struct af_instance *conv = s->last->prev;
+ if (!conv->auto_inserted)
+ return AF_ERROR;
+ if (!(mp_chmap_equals_reordered(&conv->fmt_in.channels, &s->input.channels) &&
+ mp_chmap_equals_reordered(&conv->fmt_out.channels, &s->output.channels)))
+ return AF_ERROR;
+ // Also, should be the only one which does auto conversion.
+ for (struct af_instance *af = s->first->next; af != s->last; af = af->next)
+ {
+ if (af != conv && af->auto_inserted &&
+ !mp_chmap_equals_reordered(&af->fmt_in.channels, &af->fmt_out.channels))
+ return AF_ERROR;
}
+ // And not if it's the only filter.
+ if (conv->prev == s->first && conv->next == s->last)
+ return AF_ERROR;
+
+ *cfg = s->output;
+ return AF_OK;
}
// Return AF_OK on success or AF_ERROR on failure.
-// Warning:
-// A failed af_reinit() leaves the audio chain behind in a useless, broken
-// state (for example, format filters that were tentatively inserted stay
-// inserted).
-// In that case, you should always rebuild the filter chain, or abort.
-static int af_reinit(struct af_stream *s)
-{
+static int af_do_reinit(struct af_stream *s, bool second_pass)
+{
+ struct mp_audio convert_early = {0};
+ if (second_pass) {
+ // If a channel conversion happens, and it is done by an auto-inserted
+ // filter, then insert a filter to convert it early. Otherwise, do
+ // nothing and return immediately.
+ if (af_find_output_conversion(s, &convert_early) != AF_OK)
+ return AF_OK;
+ }
+
remove_auto_inserted_filters(s);
af_chain_forget_frames(s);
reset_formats(s);
s->first->fmt_in = s->first->fmt_out = s->input;
+
+ if (mp_audio_config_valid(&convert_early)) {
+ struct af_instance *new = af_prepend(s, s->first, "lavrresample", NULL);
+ if (!new)
+ return AF_ERROR;
+ new->auto_inserted = true;
+ mp_audio_copy_config(new->data, &convert_early);
+ int rv = filter_reinit(new);
+ if (rv != AF_DETACH && rv != AF_OK)
+ return AF_ERROR;
+ MP_VERBOSE(s, "Moving up output conversion.\n");
+ }
+
// 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 +426,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 +443,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
@@ -477,6 +466,19 @@ error:
return AF_ERROR;
}
+static int af_reinit(struct af_stream *s)
+{
+ int r = af_do_reinit(s, false);
+ if (r == AF_OK && mp_audio_config_valid(&s->output)) {
+ r = af_do_reinit(s, true);
+ if (r != AF_OK) {
+ MP_ERR(s, "Failed second pass filter negotiation.\n");
+ r = af_do_reinit(s, false);
+ }
+ }
+ return r;
+}
+
// Uninit and remove all filters
void af_uninit(struct af_stream *s)
{
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_delay.c b/audio/filter/af_delay.c
deleted file mode 100644
index 8d1cca8a72..0000000000
--- a/audio/filter/af_delay.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * This audio filter delays the output signal for the different
- * channels and can be used for simple position panning.
- * An extension for this filter would be a reverb.
- *
- * Original author: Anders
- *
- * This file is part of mpv.
- *
- * mpv is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * mpv is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with mpv. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-
-#include "common/common.h"
-#include "af.h"
-
-#define L 65536
-
-#define UPDATEQI(qi) qi=(qi+1)&(L-1)
-
-// Data for specific instances of this filter
-typedef struct af_delay_s
-{
- void* q[AF_NCH]; // Circular queues used for delaying audio signal
- int wi[AF_NCH]; // Write index
- int ri; // Read index
- float d[AF_NCH]; // Delay [ms]
- char *delaystr;
-}af_delay_t;
-
-// Initialization and runtime control
-static int control(struct af_instance* af, int cmd, void* arg)
-{
- af_delay_t* s = af->priv;
- switch(cmd){
- case AF_CONTROL_REINIT:{
- int i;
- struct mp_audio *in = arg;
-
- if (in->bps != 1 && in->bps != 2 && in->bps != 4) {
- MP_FATAL(af, "Sample format not supported\n");
- return AF_ERROR;
- }
-
- // Free prevous delay queues
- for(i=0;i<af->data->nch;i++)
- free(s->q[i]);
-
- mp_audio_force_interleaved_format(in);
- mp_audio_copy_config(af->data, in);
-
- // Allocate new delay queues
- for(i=0;i<af->data->nch;i++){
- s->q[i] = calloc(L,af->data->bps);
- if(NULL == s->q[i])
- MP_FATAL(af, "Out of memory\n");
- }
-
- if(AF_OK != af_from_ms(AF_NCH, s->d, s->wi, af->data->rate, 0.0, 1000.0))
- return AF_ERROR;
- s->ri = 0;
- for(i=0;i<AF_NCH;i++){
- MP_DBG(af, "Channel %i delayed by %0.3fms\n",
- i,MPCLAMP(s->d[i],0.0,1000.0));
- MP_TRACE(af, "Channel %i delayed by %i samples\n",
- i,s->wi[i]);
- }
- return AF_OK;
- }
- }
- return AF_UNKNOWN;
-}
-
-// Deallocate memory
-static void uninit(struct af_instance* af)
-{
- int i;
-
- for(i=0;i<AF_NCH;i++)
- free(((af_delay_t*)(af->priv))->q[i]);
-}
-
-static int filter_frame(struct af_instance *af, struct mp_audio *c)
-{
- if (!c)
- return 0;
- af_delay_t* s = af->priv; // Setup for this instance
- int nch = c->nch; // Number of channels
- int len = mp_audio_psize(c)/c->bps; // Number of sample in data chunk
- int ri = 0;
- int ch,i;
- if (af_make_writeable(af, c) < 0) {
- talloc_free(c);
- return -1;
- }
- for(ch=0;ch<nch;ch++){
- switch(c->bps){
- case 1:{
- int8_t* a = c->planes[0];
- int8_t* q = s->q[ch];
- int wi = s->wi[ch];
- ri = s->ri;
- for(i=ch;i<len;i+=nch){
- q[wi] = a[i];
- a[i] = q[ri];
- UPDATEQI(wi);
- UPDATEQI(ri);
- }
- s->wi[ch] = wi;
- break;
- }
- case 2:{
- int16_t* a = c->planes[0];
- int16_t* q = s->q[ch];
- int wi = s->wi[ch];
- ri = s->ri;
- for(i=ch;i<len;i+=nch){
- q[wi] = a[i];
- a[i] = q[ri];
- UPDATEQI(wi);
- UPDATEQI(ri);
- }
- s->wi[ch] = wi;
- break;
- }
- case 4:{
- int32_t* a = c->planes[0];
- int32_t* q = s->q[ch];
- int wi = s->wi[ch];
- ri = s->ri;
- for(i=ch;i<len;i+=nch){
- q[wi] = a[i];
- a[i] = q[ri];
- UPDATEQI(wi);
- UPDATEQI(ri);
- }