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 <string.h>
#include <inttypes.h>
#include <assert.h>
#include <libavutil/opt.h>
#include <libavutil/audioconvert.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)
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)
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->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;
}
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)
{
struct af_resample *s = af->priv;
struct mp_audio *in = data;
struct mp_audio *out = af->data;
int in_samples = data->samples;
int in_size = data->samples * data->sstride;
int out_samples = avresample_available(s->avrctx) +
av_rescale_rnd(get_delay(s) + in_samples,
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);
int out_size = out_samples * out->sstride;
if (talloc_get_size(out->planes[0]) < out_size)
out->planes[0] = talloc_realloc_size(out, out->planes[0], out_size);
mp_audio_realloc_min(out, out->samples);
af->delay = out->bps * av_rescale_rnd(get_delay(s),
s->ctx.out_rate, s->ctx.in_rate,
AV_ROUND_UP);
#if USE_SET_CHANNEL_MAPPING
(void)in_size;
#else
reorder_channels(data->planes[0], s->reorder_in, data->bps, data->nch, in_samples);
#if !USE_SET_CHANNEL_MAPPING
do_reorder(in, s->reorder_in);
#endif
if (out_samples) {
out_samples = avresample_convert(s->avrctx,
(uint8_t **) out->planes, out_size, out_samples,
(uint8_t **) in->planes, in_size, in_samples);
if (out_samples < 0)
if (out->samples) {
out->samples = avresample_convert(s->avrctx,
(uint8_t **) out->planes, out->samples * out->sstride, out->samples,
(uint8_t **) in->planes, in->samples * in->sstride, in->samples);
if (out->samples < 0)
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 (needs_reorder(s->reorder_out, out->nch)) {
if (talloc_get_size(s->reorder_buffer) < out_size)
s->reorder_buffer = talloc_realloc_size(s, s->reorder_buffer, out_size);
data->planes[0] = s->reorder_buffer;
out_samples = avresample_convert(s->avrctx_out,
(uint8_t **) data->planes, out_size, out_samples,
(uint8_t **) out->planes, out_size, out_samples);
if (af_fmt_is_planar(out->format)) {
reorder_planes(data, s->reorder_out);
} else {
int out_size = out->samples * out->sstride;
if (talloc_get_size(s->reorder_buffer) < out_size)
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
reorder_channels(data->planes[0], s->reorder_out, out->bps, out->nch, out_samples);
do_reorder(data, s->reorder_out);
#endif
data->samples = out_samples;
return data;
}