af_lavrresample: add support for non-interleaved audio

This commit is contained in:
wm4 2013-11-10 23:17:04 +01:00
parent bf60281ffb
commit 45d1510e4e
1 changed files with 45 additions and 27 deletions

View File

@ -24,6 +24,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <assert.h>
#include <libavutil/opt.h> #include <libavutil/opt.h>
#include <libavutil/audioconvert.h> #include <libavutil/audioconvert.h>
#include <libavutil/common.h> #include <libavutil/common.h>
@ -244,10 +246,8 @@ static int control(struct af_instance *af, int cmd, void *arg)
if (af_to_avformat(in->format) == AV_SAMPLE_FMT_NONE) if (af_to_avformat(in->format) == AV_SAMPLE_FMT_NONE)
mp_audio_set_format(in, AF_FORMAT_FLOAT_NE); mp_audio_set_format(in, AF_FORMAT_FLOAT_NE);
mp_audio_force_interleaved_format(in);
if (af_to_avformat(out->format) == AV_SAMPLE_FMT_NONE) if (af_to_avformat(out->format) == AV_SAMPLE_FMT_NONE)
mp_audio_set_format(out, in->format); mp_audio_set_format(out, in->format);
mp_audio_force_interleaved_format(out);
af->mul = (double) (out->rate * out->nch) / (in->rate * in->nch); af->mul = (double) (out->rate * out->nch) / (in->rate * in->nch);
af->delay = out->nch * s->opts.filter_size / FFMIN(af->mul, 1); af->delay = out->nch * s->opts.filter_size / FFMIN(af->mul, 1);
@ -301,38 +301,51 @@ static bool needs_reorder(int *reorder, int num_ch)
return false; return false;
} }
static void reorder_planes(struct mp_audio *mpa, int *reorder)
{
struct mp_audio prev = *mpa;
for (int n = 0; n < mpa->num_planes; n++) {
assert(reorder[n] >= 0 && reorder[n] < mpa->num_planes);
mpa->planes[n] = prev.planes[reorder[n]];
}
}
#if !USE_SET_CHANNEL_MAPPING
static void do_reorder(struct mp_audio *mpa, int *reorder)
{
if (af_fmt_is_planar(mpa->format)) {
reorder_planes(mpa, reorder);
} else {
reorder_channels(mpa->planes[0], reorder, mpa->bps, mpa->nch, mpa->samples);
}
}
#endif
static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) static struct mp_audio *play(struct af_instance *af, struct mp_audio *data)
{ {
struct af_resample *s = af->priv; struct af_resample *s = af->priv;
struct mp_audio *in = data; struct mp_audio *in = data;
struct mp_audio *out = af->data; struct mp_audio *out = af->data;
out->samples = avresample_available(s->avrctx) +
int in_samples = data->samples; av_rescale_rnd(get_delay(s) + in->samples,
int in_size = data->samples * data->sstride;
int out_samples = avresample_available(s->avrctx) +
av_rescale_rnd(get_delay(s) + in_samples,
s->ctx.out_rate, s->ctx.in_rate, AV_ROUND_UP); s->ctx.out_rate, s->ctx.in_rate, AV_ROUND_UP);
int out_size = out_samples * out->sstride;
if (talloc_get_size(out->planes[0]) < out_size) mp_audio_realloc_min(out, out->samples);
out->planes[0] = talloc_realloc_size(out, out->planes[0], out_size);
af->delay = out->bps * av_rescale_rnd(get_delay(s), af->delay = out->bps * av_rescale_rnd(get_delay(s),
s->ctx.out_rate, s->ctx.in_rate, s->ctx.out_rate, s->ctx.in_rate,
AV_ROUND_UP); AV_ROUND_UP);
#if USE_SET_CHANNEL_MAPPING #if !USE_SET_CHANNEL_MAPPING
(void)in_size; do_reorder(in, s->reorder_in);
#else
reorder_channels(data->planes[0], s->reorder_in, data->bps, data->nch, in_samples);
#endif #endif
if (out_samples) { if (out->samples) {
out_samples = avresample_convert(s->avrctx, out->samples = avresample_convert(s->avrctx,
(uint8_t **) out->planes, out_size, out_samples, (uint8_t **) out->planes, out->samples * out->sstride, out->samples,
(uint8_t **) in->planes, in_size, in_samples); (uint8_t **) in->planes, in->samples * in->sstride, in->samples);
if (out_samples < 0) if (out->samples < 0)
return NULL; // error return NULL; // error
} }
@ -340,18 +353,23 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data)
#if USE_SET_CHANNEL_MAPPING #if USE_SET_CHANNEL_MAPPING
if (needs_reorder(s->reorder_out, out->nch)) { if (needs_reorder(s->reorder_out, out->nch)) {
if (talloc_get_size(s->reorder_buffer) < out_size) if (af_fmt_is_planar(out->format)) {
s->reorder_buffer = talloc_realloc_size(s, s->reorder_buffer, out_size); reorder_planes(data, s->reorder_out);
data->planes[0] = s->reorder_buffer; } else {
out_samples = avresample_convert(s->avrctx_out, int out_size = out->samples * out->sstride;
(uint8_t **) data->planes, out_size, out_samples, if (talloc_get_size(s->reorder_buffer) < out_size)
(uint8_t **) out->planes, out_size, out_samples); s->reorder_buffer = talloc_realloc_size(s, s->reorder_buffer, out_size);
data->planes[0] = s->reorder_buffer;
int out_samples = avresample_convert(s->avrctx_out,
(uint8_t **) data->planes, out_size, out->samples,
(uint8_t **) out->planes, out_size, out->samples);
assert(out_samples == data->samples);
}
} }
#else #else
reorder_channels(data->planes[0], s->reorder_out, out->bps, out->nch, out_samples); do_reorder(data, s->reorder_out);
#endif #endif
data->samples = out_samples;
return data; return data;
} }