From b2d4b5ee43206f8c4491b3af1c24fedd35dbdc31 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 10 Nov 2013 23:10:16 +0100 Subject: audio/format: add non-interleaved audio formats --- audio/fmt-conversion.c | 6 ++++++ audio/format.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ audio/format.h | 22 ++++++++++++++++++++-- 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/audio/fmt-conversion.c b/audio/fmt-conversion.c index 94f1fbd1f3..93fda3eaa0 100644 --- a/audio/fmt-conversion.c +++ b/audio/fmt-conversion.c @@ -32,6 +32,12 @@ static const struct { {AV_SAMPLE_FMT_FLT, AF_FORMAT_FLOAT_NE}, {AV_SAMPLE_FMT_DBL, AF_FORMAT_DOUBLE_NE}, + {AV_SAMPLE_FMT_U8P, AF_FORMAT_U8P}, + {AV_SAMPLE_FMT_S16P, AF_FORMAT_S16P}, + {AV_SAMPLE_FMT_S32P, AF_FORMAT_S32P}, + {AV_SAMPLE_FMT_FLTP, AF_FORMAT_FLOATP}, + {AV_SAMPLE_FMT_DBLP, AF_FORMAT_DOUBLEP}, + {AV_SAMPLE_FMT_NONE, 0}, }; diff --git a/audio/format.c b/audio/format.c index 448b670671..d0cd04cb88 100644 --- a/audio/format.c +++ b/audio/format.c @@ -23,7 +23,9 @@ #include #include #include +#include +#include "mpvcore/mp_common.h" #include "audio/filter/af.h" int af_fmt2bits(int format) @@ -62,6 +64,46 @@ int af_fmt_change_bits(int format, int bits) return af_fmt_is_valid(format) ? format : 0; } +static const int planar_formats[][2] = { + {AF_FORMAT_U8P, AF_FORMAT_U8}, + {AF_FORMAT_S16P, AF_FORMAT_S16}, + {AF_FORMAT_S32P, AF_FORMAT_S32}, + {AF_FORMAT_FLOATP, AF_FORMAT_FLOAT}, + {AF_FORMAT_DOUBLEP, AF_FORMAT_DOUBLE}, +}; + +// Return the planar format corresponding to the given format. +// If the format is already planar, return it. +// Return 0 if there's no equivalent. +int af_fmt_to_planar(int format) +{ + for (int n = 0; n < MP_ARRAY_SIZE(planar_formats); n++) { + if (planar_formats[n][1] == format) + return planar_formats[n][0]; + if (planar_formats[n][0] == format) + return format; + } + return 0; +} + +// Return the interleaved format corresponding to the given format. +// If the format is already interleaved, return it. +// Always succeeds if format is actually planar; otherwise return 0. +int af_fmt_from_planar(int format) +{ + for (int n = 0; n < MP_ARRAY_SIZE(planar_formats); n++) { + if (planar_formats[n][0] == format) + return planar_formats[n][1]; + } + return format; +} + +// false for interleaved and AF_FORMAT_UNKNOWN +bool af_fmt_is_planar(int format) +{ + return !!(format & AF_FORMAT_PLANAR); +} + #define FMT(string, id) \ {string, id}, @@ -87,6 +129,12 @@ const struct af_fmt_entry af_fmtstr_table[] = { FMT_ENDIAN("float", AF_FORMAT_FLOAT) FMT_ENDIAN("double", AF_FORMAT_DOUBLE) + FMT("u8p", AF_FORMAT_U8P) + FMT("s16p", AF_FORMAT_S16P) + FMT("s32p", AF_FORMAT_S32P) + FMT("floatp", AF_FORMAT_FLOATP) + FMT("doublep", AF_FORMAT_DOUBLEP) + {0} }; @@ -111,6 +159,7 @@ const char *af_fmt_to_str(int format) int af_fmt_seconds_to_bytes(int format, float seconds, int channels, int samplerate) { + assert(!af_fmt_is_planar(format)); int bps = (af_fmt2bits(format) / 8); int framelen = channels * bps; int bytes = seconds * bps * samplerate; diff --git a/audio/format.h b/audio/format.h index 95e792340c..9b855e4689 100644 --- a/audio/format.h +++ b/audio/format.h @@ -23,6 +23,7 @@ #ifndef MPLAYER_AF_FORMAT_H #define MPLAYER_AF_FORMAT_H +#include #include #include "config.h" #include "mpvcore/bstr.h" @@ -64,9 +65,15 @@ #define AF_FORMAT_F (2<<9) // Foating point #define AF_FORMAT_POINT_MASK (3<<9) -#define AF_FORMAT_MASK ((1<<11)-1) +// Interleaving (planar formats have data for each channel in separate planes) +#define AF_FORMAT_INTERLEAVED (0<<11) // must be 0 +#define AF_FORMAT_PLANAR (1<<11) +#define AF_FORMAT_INTERLEAVING_MASK (1<<11) -// PREDEFINED formats +#define AF_FORMAT_MASK ((1<<12)-1) + +#define AF_INTP (AF_FORMAT_I|AF_FORMAT_PLANAR) +#define AF_FLTP (AF_FORMAT_F|AF_FORMAT_PLANAR) // actual sample formats enum af_format { @@ -101,6 +108,13 @@ enum af_format { AF_FORMAT_MPEG2 = (AF_FORMAT_S_MPEG2), + // Planar variants + AF_FORMAT_U8P = (AF_INTP|AF_FORMAT_US|AF_FORMAT_8BIT|AF_FORMAT_NE), + AF_FORMAT_S16P = (AF_INTP|AF_FORMAT_SI|AF_FORMAT_16BIT|AF_FORMAT_NE), + AF_FORMAT_S32P = (AF_INTP|AF_FORMAT_US|AF_FORMAT_32BIT|AF_FORMAT_NE), + AF_FORMAT_FLOATP = (AF_FLTP|AF_FORMAT_32BIT|AF_FORMAT_NE), + AF_FORMAT_DOUBLEP = (AF_FLTP|AF_FORMAT_32BIT|AF_FORMAT_NE), + // Native endian variants AF_FORMAT_U16 = AF_SELECT_LE_BE(AF_FORMAT_U16_LE, AF_FORMAT_U16_BE), AF_FORMAT_S16 = AF_SELECT_LE_BE(AF_FORMAT_S16_LE, AF_FORMAT_S16_BE), @@ -150,6 +164,10 @@ const char *af_fmt_to_str(int format); int af_fmt2bits(int format); int af_fmt_change_bits(int format, int bits); +int af_fmt_to_planar(int format); +int af_fmt_from_planar(int format); +bool af_fmt_is_planar(int format); + // Amount of bytes that contain audio of the given duration, aligned to frames. int af_fmt_seconds_to_bytes(int format, float seconds, int channels, int samplerate); -- cgit v1.2.3 From d2e7467eb203d3a34bc1111564c7058b5e9c6b12 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 10 Nov 2013 23:11:40 +0100 Subject: audio/filter: prepare filter chain for non-interleaved audio Based on earlier work by Stefano Pigozzi. There are 2 changes: 1. Instead of mp_audio.audio, mp_audio.planes[0] must be used. 2. mp_audio.len used to contain the size of the audio in bytes. Now mp_audio.samples must be used. (Where 1 sample is the smallest unit of audio that covers all channels.) Also, some filters need changes to reject non-interleaved formats properly. Nothing uses the non-interleaved features yet, but this is needed so that things don't just break when doing so. --- audio/audio.c | 148 +++++++++++++++++++++++++++++++++--- audio/audio.h | 31 ++++++-- audio/decode/dec_audio.c | 12 +-- audio/filter/af.c | 46 +++++------ audio/filter/af_bs2b.c | 2 +- audio/filter/af_center.c | 4 +- audio/filter/af_channels.c | 16 ++-- audio/filter/af_convert24.c | 15 ++-- audio/filter/af_convertsignendian.c | 9 ++- audio/filter/af_delay.c | 9 ++- audio/filter/af_drc.c | 17 +++-- audio/filter/af_equalizer.c | 6 +- audio/filter/af_export.c | 4 +- audio/filter/af_extrastereo.c | 9 ++- audio/filter/af_format.c | 5 +- audio/filter/af_hrtf.c | 11 ++- audio/filter/af_karaoke.c | 4 +- audio/filter/af_ladspa.c | 12 +-- audio/filter/af_lavcac3enc.c | 30 ++++---- audio/filter/af_lavfi.c | 17 +++-- audio/filter/af_lavrresample.c | 32 ++++---- audio/filter/af_pan.c | 11 ++- audio/filter/af_scaletempo.c | 27 +++---- audio/filter/af_sinesuppress.c | 4 +- audio/filter/af_sub.c | 4 +- audio/filter/af_surround.c | 11 ++- audio/filter/af_sweep.c | 4 +- audio/filter/af_volume.c | 9 ++- 28 files changed, 332 insertions(+), 177 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 9d41928436..ace455f123 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -17,42 +17,58 @@ #include +#include "mpvcore/mp_common.h" #include "mpvcore/mp_talloc.h" #include "audio.h" +static void update_redundant_info(struct mp_audio *mpa) +{ + assert(mp_chmap_is_empty(&mpa->channels) || + mp_chmap_is_valid(&mpa->channels)); + mpa->nch = mpa->channels.num; + mpa->bps = af_fmt2bits(mpa->format) / 8; + if (af_fmt_is_planar(mpa->format)) { + mpa->spf = 1; + mpa->num_planes = mpa->nch; + mpa->sstride = mpa->bps; + } else { + mpa->spf = mpa->nch; + mpa->num_planes = 1; + mpa->sstride = mpa->bps * mpa->nch; + } +} + void mp_audio_set_format(struct mp_audio *mpa, int format) { mpa->format = format; - mpa->bps = af_fmt2bits(format) / 8; + update_redundant_info(mpa); } void mp_audio_set_num_channels(struct mp_audio *mpa, int num_channels) { - struct mp_chmap map; - mp_chmap_from_channels(&map, num_channels); - mp_audio_set_channels(mpa, &map); + mp_chmap_from_channels(&mpa->channels, num_channels); + update_redundant_info(mpa); } // Use old MPlayer/ALSA channel layout. void mp_audio_set_channels_old(struct mp_audio *mpa, int num_channels) { - struct mp_chmap map; - mp_chmap_from_channels_alsa(&map, num_channels); - mp_audio_set_channels(mpa, &map); + mp_chmap_from_channels_alsa(&mpa->channels, num_channels); + update_redundant_info(mpa); } void mp_audio_set_channels(struct mp_audio *mpa, const struct mp_chmap *chmap) { - assert(mp_chmap_is_empty(chmap) || mp_chmap_is_valid(chmap)); mpa->channels = *chmap; - mpa->nch = mpa->channels.num; + update_redundant_info(mpa); } void mp_audio_copy_config(struct mp_audio *dst, const struct mp_audio *src) { - mp_audio_set_format(dst, src->format); - mp_audio_set_channels(dst, &src->channels); + dst->format = src->format; + dst->channels = src->channels; dst->rate = src->rate; + update_redundant_info(dst); } bool mp_audio_config_equals(const struct mp_audio *a, const struct mp_audio *b) @@ -74,3 +90,113 @@ char *mp_audio_config_to_str(struct mp_audio *mpa) { return mp_audio_fmt_to_str(mpa->rate, &mpa->channels, mpa->format); } + +void mp_audio_force_interleaved_format(struct mp_audio *mpa) +{ + if (af_fmt_is_planar(mpa->format)) + mp_audio_set_format(mpa, af_fmt_from_planar(mpa->format)); +} + +// Return used size of a plane. (The size is the same for all planes.) +int mp_audio_psize(struct mp_audio *mpa) +{ + return mpa->samples * mpa->sstride; +} + +void mp_audio_set_null_data(struct mp_audio *mpa) +{ + for (int n = 0; n < MP_NUM_CHANNELS; n++) + mpa->planes[n] = NULL; + mpa->samples = 0; +} + +/* Reallocate the data stored in mpa->planes[n] so that enough samples are + * available on every plane. The previous data is kept (for the smallest + * common number of samples before/after resize). + * + * mpa->samples is not set or used. + * + * This function is flexible enough to handle format and channel layout + * changes. In these cases, all planes are reallocated as needed. Unused + * planes are freed. + * + * mp_audio_realloc(mpa, 0) will still yield non-NULL for mpa->data[n]. + * + * Allocated data is implicitly freed on talloc_free(mpa). + */ +void mp_audio_realloc(struct mp_audio *mpa, int samples) +{ + assert(samples >= 0); + int size = MPMAX(samples * mpa->sstride, 1); + for (int n = 0; n < mpa->num_planes; n++) { + mpa->planes[n] = talloc_realloc_size(mpa, mpa->planes[n], size); + } + for (int n = mpa->num_planes; n < MP_NUM_CHANNELS; n++) { + talloc_free(mpa->planes[n]); + mpa->planes[n] = NULL; + } +} + +// Like mp_audio_realloc(), but only reallocate if the audio grows in size. +void mp_audio_realloc_min(struct mp_audio *mpa, int samples) +{ + if (samples > mp_audio_get_allocated_size(mpa)) + mp_audio_realloc(mpa, samples); +} + +/* Get the size allocated for the data, in number of samples. If the allocated + * size isn't on sample boundaries (e.g. after format changes), the returned + * sample number is a rounded down value. + * + * Note that this only works in situations where mp_audio_realloc() also works! + */ +int mp_audio_get_allocated_size(struct mp_audio *mpa) +{ + int size = 0; + for (int n = 0; n < mpa->num_planes; n++) { + int s = talloc_get_size(mpa->planes[n]) / mpa->sstride; + size = n == 0 ? s : MPMIN(size, s); + } + return size; +} + +// Clear the samples [start, start + length) with silence. +void mp_audio_fill_silence(struct mp_audio *mpa, int start, int length) +{ + assert(start >= 0 && length >= 0 && start + length <= mpa->samples); + int offset = start * mpa->sstride; + int size = length * mpa->sstride; + for (int n = 0; n < mpa->num_planes; n++) { + if (n > 0 && mpa->planes[n] == mpa->planes[0]) + continue; // silly optimization for special cases + af_fill_silence((char *)mpa->planes[n] + offset, size, mpa->format); + } +} + +// All integer parameters are in samples. +// dst and src can overlap. +void mp_audio_copy(struct mp_audio *dst, int dst_offset, + struct mp_audio *src, int src_offset, int length) +{ + assert(mp_audio_config_equals(dst, src)); + assert(length >= 0); + assert(dst_offset >= 0 && dst_offset + length <= dst->samples); + assert(src_offset >= 0 && src_offset + length <= src->samples); + + for (int n = 0; n < dst->num_planes; n++) { + memmove((char *)dst->planes[n] + dst_offset * dst->sstride, + (char *)src->planes[n] + src_offset * src->sstride, + length * dst->sstride); + } +} + +// Set data to the audio after the given number of samples (i.e. slice it). +void mp_audio_skip_samples(struct mp_audio *data, int samples) +{ + assert(samples >= 0 && samples <= data->samples); + + for (int n = 0; n < data->num_planes; n++) + data->planes[n] = (uint8_t *)data->planes[n] + samples * data->sstride; + + data->samples -= samples; +} diff --git a/audio/audio.h b/audio/audio.h index de35e697c8..b5cae0c83c 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -23,14 +23,19 @@ // Audio data chunk struct mp_audio { - void *audio; // data buffer - int len; // buffer length (in bytes) - int rate; // sample rate + int samples; // number of samples in data (per channel) + void *planes[MP_NUM_CHANNELS]; // data buffer (one per plane) + int rate; // sample rate struct mp_chmap channels; // channel layout, use mp_audio_set_*() to set int format; // format (AF_FORMAT_...), use mp_audio_set_format() to set // Redundant fields, for convenience - int nch; // number of channels (redundant with chmap) - int bps; // bytes per sample (redundant with format) + int sstride; // distance between 2 samples in bytes on a plane + // interleaved: bps * nch + // planar: bps + int nch; // number of channels (redundant with chmap) + int spf; // sub-samples per sample on each plane + int num_planes; // number of planes + int bps; // size of sub-samples (af_fmt2bits(format) / 8) }; void mp_audio_set_format(struct mp_audio *mpa, int format); @@ -43,4 +48,20 @@ bool mp_audio_config_equals(const struct mp_audio *a, const struct mp_audio *b); char *mp_audio_fmt_to_str(int srate, const struct mp_chmap *chmap, int format); char *mp_audio_config_to_str(struct mp_audio *mpa); +void mp_audio_force_interleaved_format(struct mp_audio *mpa); + +int mp_audio_psize(struct mp_audio *mpa); + +void mp_audio_set_null_data(struct mp_audio *mpa); + +void mp_audio_realloc(struct mp_audio *mpa, int samples); +void mp_audio_realloc_min(struct mp_audio *mpa, int samples); +int mp_audio_get_allocated_size(struct mp_audio *mpa); + +void mp_audio_fill_silence(struct mp_audio *mpa, int start, int length); + +void mp_audio_copy(struct mp_audio *dst, int dst_offset, + struct mp_audio *src, int src_offset, int length); +void mp_audio_skip_samples(struct mp_audio *data, int samples); + #endif diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index e381a12a3c..ef7993c83a 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -270,20 +270,20 @@ static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len) // Filter struct mp_audio filter_input = { - .audio = sh->a_buffer, - .len = len, + .planes = {sh->a_buffer}, .rate = sh->samplerate, }; mp_audio_set_format(&filter_input, sh->sample_format); mp_audio_set_channels(&filter_input, &sh->channels); + filter_input.samples = len / filter_input.sstride; struct mp_audio *filter_output = af_play(sh->afilter, &filter_input); if (!filter_output) return -1; - set_min_out_buffer_size(outbuf, outbuf->len + filter_output->len); - memcpy(outbuf->start + outbuf->len, filter_output->audio, - filter_output->len); - outbuf->len += filter_output->len; + int outlen = filter_output->samples * filter_output->sstride; + set_min_out_buffer_size(outbuf, outbuf->len + outlen); + memcpy(outbuf->start + outbuf->len, filter_output->planes[0], outlen); + outbuf->len += outlen; // remove processed data from decoder buffer: sh->a_buffer_len -= len; diff --git a/audio/filter/af.c b/audio/filter/af.c index edee4bef65..95d0e43673 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -523,8 +523,7 @@ static int af_reinit(struct af_stream *s) // Check if this is the first filter struct mp_audio in = *af->prev->data; // Reset just in case... - in.audio = NULL; - in.len = 0; + mp_audio_set_null_data(&in); int rv = af->control(af, AF_CONTROL_REINIT, &in); if (rv == AF_OK && !mp_audio_config_equals(&in, af->prev->data)) @@ -640,8 +639,8 @@ int af_init(struct af_stream *s) return -1; // Precaution in case caller is misbehaving - s->input.audio = s->output.audio = NULL; - s->input.len = s->output.len = 0; + mp_audio_set_null_data(&s->input); + mp_audio_set_null_data(&s->output); // Check if this is the first call if (s->first->next == s->last) { @@ -731,36 +730,39 @@ double af_calc_delay(struct af_stream *s) return delay; } -/* Calculate the minimum output buffer size for given input data d - * when using the af_resize_local_buffer function. The +t+1 part ensures the - * value is >= len*mul rounded upwards to whole samples even if the - * double 'mul' is inexact. */ -static int af_lencalc(double mul, struct mp_audio *d) -{ - int t = d->bps * d->nch; - return d->len * mul + t + 1; -} - /* I a local buffer is used (i.e. if the filter doesn't operate on the incoming * buffer), this macro must be called to ensure the buffer is big enough. */ int af_resize_local_buffer(struct af_instance *af, struct mp_audio *data) { - if (af->data->len >= af_lencalc(af->mul, data)) + assert(data->format); + + if (!af->data->format && !af->data->planes[0]) { + // Dummy initialization + mp_audio_set_format(af->data, AF_FORMAT_U8); + } + + int oldlen = af->data->samples * af->data->sstride; + + /* Calculate the minimum output buffer size for given input data d + * when using the af_resize_local_buffer function. The +x part ensures + * the value is >= len*mul rounded upwards to whole samples even if the + * double 'mul' is inexact. */ + int newlen = data->samples * data->sstride * af->mul + data->sstride + 1; + + if (oldlen >= newlen) return AF_OK; - // Calculate new length - register int len = af_lencalc(af->mul, data); mp_msg(MSGT_AFILTER, MSGL_V, "[libaf] Reallocating memory in module %s, " - "old len = %i, new len = %i\n", af->info->name, af->data->len, len); + "old len = %i, new len = %i\n", af->info->name, oldlen, newlen); // If there is a buffer free it - free(af->data->audio); + free(af->data->planes[0]); // Create new buffer and check that it is OK - af->data->audio = malloc(len); - if (!af->data->audio) { + af->data->planes[0] = malloc(newlen); + if (!af->data->planes[0]) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[libaf] Could not allocate memory \n"); return AF_ERROR; } - af->data->len = len; + af->data->samples = newlen / af->data->sstride; return AF_OK; } diff --git a/audio/filter/af_bs2b.c b/audio/filter/af_bs2b.c index 0e77b3e4eb..5e0caf28af 100644 --- a/audio/filter/af_bs2b.c +++ b/audio/filter/af_bs2b.c @@ -42,7 +42,7 @@ static struct mp_audio *play_##name(struct af_instance *af, struct mp_audio *dat { \ /* filter is called for all pairs of samples available in the buffer */ \ bs2b_cross_feed_##name(((struct af_bs2b*)(af->priv))->filter, \ - (type*)(data->audio), data->len/data->bps/2); \ + (type*)(data->planes[0]), data->samples); \ \ return data; \ } diff --git a/audio/filter/af_center.c b/audio/filter/af_center.c index 0cfdbc3b0e..c64c551f1c 100644 --- a/audio/filter/af_center.c +++ b/audio/filter/af_center.c @@ -87,9 +87,9 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) { struct mp_audio* c = data; // Current working data af_center_t* s = af->setup; // Setup for this instance - float* a = c->audio; // Audio data - int len = c->len/4; // Number of samples in current audio block + float* a = c->planes[0]; // Audio data int nch = c->nch; // Number of channels + int len = c->samples*c->nch; // Number of samples in current audio block int ch = s->ch; // Channel in which to insert the center audio register int i; diff --git a/audio/filter/af_channels.c b/audio/filter/af_channels.c index 27445aafe2..fd3b8262f5 100644 --- a/audio/filter/af_channels.c +++ b/audio/filter/af_channels.c @@ -169,6 +169,10 @@ static int control(struct af_instance* af, int cmd, void* arg) af->data->rate = ((struct mp_audio*)arg)->rate; mp_audio_set_format(af->data, ((struct mp_audio*)arg)->format); af->mul = (double)af->data->nch / ((struct mp_audio*)arg)->nch; + mp_audio_force_interleaved_format(af->data); + int r = af_test_output(af,(struct mp_audio*)arg); + if (r != AF_OK) + return r; return check_routes(s,((struct mp_audio*)arg)->nch,af->data->nch); case AF_CONTROL_COMMAND_LINE:{ int nch = 0; @@ -219,7 +223,7 @@ static void uninit(struct af_instance* af) { free(af->setup); if (af->data) - free(af->data->audio); + free(af->data->planes[0]); free(af->data); } @@ -235,16 +239,16 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) return NULL; // Reset unused channels - memset(l->audio,0,c->len / c->nch * l->nch); + memset(l->planes[0],0,mp_audio_psize(c) / c->nch * l->nch); if(AF_OK == check_routes(s,c->nch,l->nch)) for(i=0;inr;i++) - copy(c->audio,l->audio,c->nch,s->route[i][FR], - l->nch,s->route[i][TO],c->len,c->bps); + copy(c->planes[0],l->planes[0],c->nch,s->route[i][FR], + l->nch,s->route[i][TO],mp_audio_psize(c),c->bps); // Set output data - c->audio = l->audio; - c->len = c->len / c->nch * l->nch; + c->planes[0] = l->planes[0]; + c->samples = c->samples / c->nch * l->nch; mp_audio_set_channels(c, &l->channels); return c; diff --git a/audio/filter/af_convert24.c b/audio/filter/af_convert24.c index 18ce156467..96924de344 100644 --- a/audio/filter/af_convert24.c +++ b/audio/filter/af_convert24.c @@ -78,12 +78,12 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) return NULL; struct mp_audio *out = af->data; - size_t len = data->len / data->bps; + size_t len = mp_audio_psize(data) / data->bps; if (data->bps == 4) { for (int s = 0; s < len; s++) { - uint32_t val = *((uint32_t *)data->audio + s); - uint8_t *ptr = (uint8_t *)out->audio + s * 3; + uint32_t val = *((uint32_t *)data->planes[0] + s); + uint8_t *ptr = (uint8_t *)out->planes[0] + s * 3; ptr[0] = val >> SHIFT(0); ptr[1] = val >> SHIFT(1); ptr[2] = val >> SHIFT(2); @@ -91,24 +91,23 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) mp_audio_set_format(data, af_fmt_change_bits(data->format, 24)); } else { for (int s = 0; s < len; s++) { - uint8_t *ptr = (uint8_t *)data->audio + s * 3; + uint8_t *ptr = (uint8_t *)data->planes[0] + s * 3; uint32_t val = ptr[0] << SHIFT(0) | ptr[1] << SHIFT(1) | ptr[2] << SHIFT(2); - *((uint32_t *)out->audio + s) = val; + *((uint32_t *)out->planes[0] + s) = val; } mp_audio_set_format(data, af_fmt_change_bits(data->format, 32)); } - data->audio = out->audio; - data->len = len * data->bps; + data->planes[0] = out->planes[0]; return data; } static void uninit(struct af_instance* af) { if (af->data) - free(af->data->audio); + free(af->data->planes[0]); } static int af_open(struct af_instance *af) diff --git a/audio/filter/af_convertsignendian.c b/audio/filter/af_convertsignendian.c index bfea004bb2..5565438aad 100644 --- a/audio/filter/af_convertsignendian.c +++ b/audio/filter/af_convertsignendian.c @@ -24,6 +24,9 @@ static bool test_conversion(int src_format, int dst_format) { + if ((src_format & AF_FORMAT_PLANAR) || + (dst_format & AF_FORMAT_PLANAR)) + return false; int src_noend = src_format & ~AF_FORMAT_END_MASK; int dst_noend = dst_format & ~AF_FORMAT_END_MASK; // We can swap endian for all formats, but sign only for integer formats. @@ -100,13 +103,13 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) { int infmt = data->format; int outfmt = af->data->format; - size_t len = data->len / data->bps; + size_t len = data->samples * data->nch; if ((infmt & AF_FORMAT_END_MASK) != (outfmt & AF_FORMAT_END_MASK)) - endian(data->audio, len, data->bps); + endian(data->planes[0], len, data->bps); if ((infmt & AF_FORMAT_SIGN_MASK) != (outfmt & AF_FORMAT_SIGN_MASK)) - si2us(data->audio, len, data->bps, + si2us(data->planes[0], len, data->bps, (outfmt & AF_FORMAT_END_MASK) == AF_FORMAT_LE); mp_audio_set_format(data, outfmt); diff --git a/audio/filter/af_delay.c b/audio/filter/af_delay.c index a6515f84cf..c979060fe3 100644 --- a/audio/filter/af_delay.c +++ b/audio/filter/af_delay.c @@ -56,6 +56,7 @@ static int control(struct af_instance* af, int cmd, void* arg) free(s->q[i]); mp_audio_copy_config(af->data, (struct mp_audio*)arg); + mp_audio_force_interleaved_format(af->data); // Allocate new delay queues for(i=0;idata->nch;i++){ @@ -123,13 +124,13 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) struct mp_audio* c = data; // Current working data af_delay_t* s = af->setup; // Setup for this instance int nch = c->nch; // Number of channels - int len = c->len/c->bps; // Number of sample in data chunk + int len = mp_audio_psize(c)/c->bps; // Number of sample in data chunk int ri = 0; int ch,i; for(ch=0;chbps){ case 1:{ - int8_t* a = c->audio; + int8_t* a = c->planes[0]; int8_t* q = s->q[ch]; int wi = s->wi[ch]; ri = s->ri; @@ -143,7 +144,7 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) break; } case 2:{ - int16_t* a = c->audio; + int16_t* a = c->planes[0]; int16_t* q = s->q[ch]; int wi = s->wi[ch]; ri = s->ri; @@ -157,7 +158,7 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) break; } case 4:{ - int32_t* a = c->audio; + int32_t* a = c->planes[0]; int32_t* q = s->q[ch]; int wi = s->wi[ch]; ri = s->ri; diff --git a/audio/filter/af_drc.c b/audio/filter/af_drc.c index 9bbbde4831..589844d89b 100644 --- a/audio/filter/af_drc.c +++ b/audio/filter/af_drc.c @@ -88,6 +88,7 @@ static int control(struct af_instance* af, int cmd, void* arg) // Sanity check if(!arg) return AF_ERROR; + mp_audio_force_interleaved_format((struct mp_audio*)arg); mp_audio_copy_config(af->data, (struct mp_audio*)arg); if(((struct mp_audio*)arg)->format != (AF_FORMAT_S16_NE)){ @@ -119,8 +120,8 @@ static void uninit(struct af_instance* af) static void method1_int16(af_drc_t *s, struct mp_audio *c) { register int i = 0; - int16_t *data = (int16_t*)c->audio; // Audio data - int len = c->len/2; // Number of samples + int16_t *data = (int16_t*)c->planes[0]; // Audio data + int len = c->samples*c->nch; // Number of samples float curavg = 0.0, newavg, neededmul; int tmp; @@ -161,8 +162,8 @@ static void method1_int16(af_drc_t *s, struct mp_audio *c) static void method1_float(af_drc_t *s, struct mp_audio *c) { register int i = 0; - float *data = (float*)c->audio; // Audio data - int len = c->len/4; // Number of samples + float *data = (float*)c->planes[0]; // Audio data + int len = c->samples*c->nch; // Number of samples float curavg = 0.0, newavg, neededmul, tmp; for (i = 0; i < len; i++) @@ -198,8 +199,8 @@ static void method1_float(af_drc_t *s, struct mp_audio *c) static void method2_int16(af_drc_t *s, struct mp_audio *c) { register int i = 0; - int16_t *data = (int16_t*)c->audio; // Audio data - int len = c->len/2; // Number of samples + int16_t *data = (int16_t*)c->planes[0]; // Audio data + int len = c->samples*c->nch; // Number of samples float curavg = 0.0, newavg, avg = 0.0; int tmp, totallen = 0; @@ -248,8 +249,8 @@ static void method2_int16(af_drc_t *s, struct mp_audio *c) static void method2_float(af_drc_t *s, struct mp_audio *c) { register int i = 0; - float *data = (float*)c->audio; // Audio data - int len = c->len/4; // Number of samples + float *data = (float*)c->planes[0]; // Audio data + int len = c->samples*c->nch; // Number of samples float curavg = 0.0, newavg, avg = 0.0, tmp; int totallen = 0; diff --git a/audio/filter/af_equalizer.c b/audio/filter/af_equalizer.c index cbdcd3f84a..718445c001 100644 --- a/audio/filter/af_equalizer.c +++ b/audio/filter/af_equalizer.c @@ -170,9 +170,9 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) while(ci--){ float* g = s->g[ci]; // Gain factor - float* in = ((float*)c->audio)+ci; - float* out = ((float*)c->audio)+ci; - float* end = in + c->len/4; // Block loop end + float* in = ((float*)c->planes[0])+ci; + float* out = ((float*)c->planes[0])+ci; + float* end = in + c->samples*c->nch; // Block loop end while(in < end){ register int k = 0; // Frequency band index diff --git a/audio/filter/af_export.c b/audio/filter/af_export.c index 45143075a1..a6ebdc322e 100644 --- a/audio/filter/af_export.c +++ b/audio/filter/af_export.c @@ -213,9 +213,9 @@ static struct mp_audio* play( struct af_instance* af, struct mp_audio* data ) { struct mp_audio* c = data; // Current working data af_export_t* s = af->setup; // Setup for this instance - int16_t* a = c->audio; // Incomming sound + int16_t* a = c->planes[0]; // Incomming sound int nch = c->nch; // Number of channels - int len = c->len/c->bps; // Number of sample in data chunk + int len = c->samples*c->nch; // Number of sample in data chunk int sz = s->sz; // buffer size (in samples) int flag = 0; // Set to 1 if buffer is filled diff --git a/audio/filter/af_extrastereo.c b/audio/filter/af_extrastereo.c index 4cf27f2724..5b3792763b 100644 --- a/audio/filter/af_extrastereo.c +++ b/audio/filter/af_extrastereo.c @@ -49,6 +49,7 @@ static int control(struct af_instance* af, int cmd, void* arg) if(!arg) return AF_ERROR; mp_audio_copy_config(af->data, (struct mp_audio*)arg); + mp_audio_force_interleaved_format(af->data); mp_audio_set_num_channels(af->data, 2); if (af->data->format == AF_FORMAT_FLOAT_NE) { @@ -83,8 +84,8 @@ static struct mp_audio* play_s16(struct af_instance* af, struct mp_audio* data) { af_extrastereo_t *s = af->setup; register int i = 0; - int16_t *a = (int16_t*)data->audio; // Audio data - int len = data->len/2; // Number of samples + int16_t *a = (int16_t*)data->planes[0]; // Audio data + int len = data->samples*data->nch; // Number of samples int avg, l, r; for (i = 0; i < len; i+=2) @@ -105,8 +106,8 @@ static struct mp_audio* play_float(struct af_instance* af, struct mp_audio* data { af_extrastereo_t *s = af->setup; register int i = 0; - float *a = (float*)data->audio; // Audio data - int len = data->len/4; // Number of samples + float *a = (float*)data->planes[0]; // Audio data + int len = data->samples * data->nch; // Number of samples float avg, l, r; for (i = 0; i < len; i+=2) diff --git a/audio/filter/af_format.c b/audio/filter/af_format.c index 642ef927bb..b551ddba42 100644 --- a/audio/filter/af_format.c +++ b/audio/filter/af_format.c @@ -105,8 +105,9 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) struct mp_audio *r = &priv->temp; *r = *af->data; - r->audio = data->audio; - r->len = data->len; + for (int n = 0; n < r->nch; n++) + r->planes[n] = data->planes[n]; + r->samples = data->samples; return r; } diff --git a/audio/filter/af_hrtf.c b/audio/filter/af_hrtf.c index 5b80bf0eec..01148dc6a6 100644 --- a/audio/filter/af_hrtf.c +++ b/audio/filter/af_hrtf.c @@ -367,7 +367,7 @@ static void uninit(struct af_instance *af) free(af->setup); } if(af->data) - free(af->data->audio); + free(af->data->planes[0]); free(af->data); } @@ -385,9 +385,9 @@ damped (without any real 3D acoustical image, however). static struct mp_audio* play(struct af_instance *af, struct mp_audio *data) { af_hrtf_t *s = af->setup; - short *in = data->audio; // Input audio data + short *in = data->planes[0]; // Input audio data short *out = NULL; // Output audio data - short *end = in + data->len / sizeof(short); // Loop end + short *end = in + data->samples * data->nch; // Loop end float common, left, right, diff, left_b, right_b; const int dblen = s->dlbuflen, hlen = s->hrflen, blen = s->basslen; @@ -425,7 +425,7 @@ static struct mp_audio* play(struct af_instance *af, struct mp_audio *data) "channel\n"); } - out = af->data->audio; + out = af->data->planes[0]; /* MPlayer's 5 channel layout (notation for the variable): * @@ -565,8 +565,7 @@ static struct mp_audio* play(struct af_instance *af, struct mp_audio *data) } /* Set output data */ - data->audio = af->data->audio; - data->len = data->len / data->nch * 2; + data->planes[0] = af->data->planes[0]; mp_audio_set_num_channels(data, 2); return data; diff --git a/audio/filter/af_karaoke.c b/audio/filter/af_karaoke.c index b24ba0d877..d9c62aa85c 100644 --- a/audio/filter/af_karaoke.c +++ b/audio/filter/af_karaoke.c @@ -51,9 +51,9 @@ static void uninit(struct af_instance* af) static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) { struct mp_audio* c = data; // Current working data - float* a = c->audio; // Audio data - int len = c->len/4; // Number of samples in current audio block + float* a = c->planes[0]; // Audio data int nch = c->nch; // Number of channels + int len = c->samples*nch; // Number of samples in current audio block register int i; /* diff --git a/audio/filter/af_ladspa.c b/audio/filter/af_ladspa.c index 73b7430201..6acdc150d7 100644 --- a/audio/filter/af_ladspa.c +++ b/audio/filter/af_ladspa.c @@ -497,10 +497,6 @@ static int control(struct af_instance *af, int cmd, void *arg) { mp_audio_copy_config(af->data, (struct mp_audio*)arg); mp_audio_set_format(af->data, AF_FORMAT_FLOAT_NE); - /* arg->len is not set here yet, so init of buffers and connecting the - * filter, has to be done in play() :-/ - */ - return af_test_output(af, (struct mp_audio*)arg); case AF_CONTROL_COMMAND_LINE: { char *buf; @@ -710,8 +706,8 @@ static void uninit(struct af_instance *af) { static struct mp_audio* play(struct af_instance *af, struct mp_audio *data) { af_ladspa_t *setup = af->setup; const LADSPA_Descriptor *pdes = setup->plugin_descriptor; - float *audio = (float*)data->audio; - int nsamples = data->len/4; /* /4 because it's 32-bit float */ + float *audio = (float*)data->planes[0]; + int nsamples = data->samples*data->nch; int nch = data->nch; int rate = data->rate; int i, p; @@ -723,10 +719,6 @@ static struct mp_audio* play(struct af_instance *af, struct mp_audio *data) { * plugin, connect ports and activate plugin */ - /* 2004-12-07: Also check if the buffersize has to be changed! - * data->len is not constant per se! re-init buffers. - */ - if ( (setup->bufsize != nsamples/nch) || (setup->nch != nch) ) { /* if setup->nch==0, it's the first call, if not, something has diff --git a/audio/filter/af_lavcac3enc.c b/audio/filter/af_lavcac3enc.c index 9ca193017a..d4abf2e942 100644 --- a/audio/filter/af_lavcac3enc.c +++ b/audio/filter/af_lavcac3enc.c @@ -161,7 +161,7 @@ static void uninit(struct af_instance* af) af_ac3enc_t *s = af->setup; if (af->data) - free(af->data->audio); + free(af->data->planes[0]); free(af->data); if (s) { av_free_packet(&s->pkt); @@ -183,7 +183,7 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* audio) int left, outsize = 0; char *buf, *src; int max_output_len; - int frame_num = (audio->len + s->pending_len) / s->expect_len; + int frame_num = (mp_audio_psize(audio) + s->pending_len) / s->expect_len; int samplesize = af_fmt2bits(s->in_sampleformat) / 8; if (s->add_iec61937_header) @@ -191,23 +191,23 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* audio) else max_output_len = AC3_MAX_CODED_FRAME_SIZE * frame_num; - if (af->data->len < max_output_len) { + if (mp_audio_psize(af->data) < max_output_len) { mp_msg(MSGT_AFILTER, MSGL_V, "[libaf] Reallocating memory in module %s, " - "old len = %i, new len = %i\n", af->info->name, af->data->len, - max_output_len); - free(af->data->audio); - af->data->audio = malloc(max_output_len); - if (!af->data->audio) { + "old len = %i, new len = %i\n", af->info->name, + mp_audio_psize(af->data), max_output_len); + free(af->data->planes[0]); + af->data->planes[0] = malloc(max_output_len); + if (!af->data->planes[0]) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[libaf] Could not allocate memory \n"); return NULL; } - af->data->len = max_output_len; + af->data->samples = max_output_len / af->data->sstride; } l = af->data; // Local data - buf = l->audio; - src = c->audio; - left = c->len; + buf = l->planes[0]; + src = c->planes[0]; + left = mp_audio_psize(c); while (left > 0) { @@ -296,7 +296,7 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* audio) len = AC3_FRAME_SIZE * 2 * 2; } - assert(buf + len <= (char *)af->data->audio + af->data->len); + assert(buf + len <= (char *)af->data->planes[0] + mp_audio_psize(af->data)); assert(s->pkt.size <= len - header_len); memcpy(buf + header_len, s->pkt.data, s->pkt.size); @@ -304,10 +304,10 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* audio) outsize += len; buf += len; } - c->audio = l->audio; + c->planes[0] = l->planes[0]; mp_audio_set_num_channels(c, 2); mp_audio_set_format(c, af->data->format); - c->len = outsize; + c->samples = outsize / c->sstride; mp_msg(MSGT_AFILTER, MSGL_DBG2, "play return size %d, pending %d\n", outsize, s->pending_len); return c; diff --git a/audio/filter/af_lavfi.c b/audio/filter/af_lavfi.c index 3c6d981f1d..f08e7ff85c 100644 --- a/audio/filter/af_lavfi.c +++ b/audio/filter/af_lavfi.c @@ -181,6 +181,7 @@ 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 (!mp_chmap_is_lavc(&in->channels)) mp_chmap_reorder_to_lavc(&in->channels); // will always work @@ -193,6 +194,7 @@ static int control(struct af_instance *af, int cmd, void *arg) out->rate = l_out->sample_rate; mp_audio_set_format(out, af_from_avformat(l_out->format)); + mp_audio_force_interleaved_format(out); struct mp_chmap out_cm; mp_chmap_from_lavc(&out_cm, l_out->channel_layout); @@ -228,7 +230,7 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) int out_frame_size = r->bps * r->channels.num; AVFrame *frame = av_frame_alloc(); - frame->nb_samples = data->len / in_frame_size; + frame->nb_samples = data->samples; frame->format = l_in->format; // Timebase is 1/sample_rate @@ -238,7 +240,7 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) av_frame_set_channel_layout(frame, l_in->channel_layout); av_frame_set_sample_rate(frame, l_in->sample_rate); - frame->data[0] = data->audio; + frame->data[0] = data->planes[0]; frame->extended_data = frame->data; if (av_buffersrc_add_frame(p->in, frame) < 0) { @@ -268,11 +270,11 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) av_frame_free(&frame); } - r->audio = p->out_buffer; - r->len = out_len; + r->planes[0] = p->out_buffer; + r->samples = out_len / r->sstride; - p->bytes_in += data->len; - p->bytes_out += r->len; + p->bytes_in += data->samples * data->sstride; + p->bytes_out += r->samples * r->sstride; if (out_pts != AV_NOPTS_VALUE) { int64_t num_in_frames = p->bytes_in / in_frame_size; @@ -280,8 +282,7 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) double out_time = out_pts * av_q2d(p->timebase_out); // Need pts past the last output sample. - int out_frames = r->len / out_frame_size; - out_time += out_frames / (double)r->rate; + out_time += r->samples / (double)r->rate; af->delay = (in_time - out_time) * r->rate * out_frame_size; } diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c index 860e5a52d3..a6abd32aed 100644 --- a/audio/filter/af_lavrresample.c +++ b/audio/filter/af_lavrresample.c @@ -244,8 +244,10 @@ 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); @@ -306,28 +308,30 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) struct mp_audio *out = af->data; - int in_size = data->len; - int in_samples = in_size / (data->bps * data->nch); + 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, s->ctx.out_rate, s->ctx.in_rate, AV_ROUND_UP); - int out_size = out->bps * out_samples * out->nch; + int out_size = out_samples * out->sstride; - if (talloc_get_size(out->audio) < out_size) - out->audio = talloc_realloc_size(out, out->audio, out_size); + if (talloc_get_size(out->planes[0]) < out_size) + out->planes[0] = talloc_realloc_size(out, out->planes[0], out_size); 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 - reorder_channels(data->audio, s->reorder_in, data->bps, data->nch, in_samples); +#if USE_SET_CHANNEL_MAPPING + (void)in_size; +#else + reorder_channels(data->planes[0], s->reorder_in, data->bps, data->nch, in_samples); #endif if (out_samples) { out_samples = avresample_convert(s->avrctx, - (uint8_t **) &out->audio, out_size, out_samples, - (uint8_t **) &in->audio, in_size, in_samples); + (uint8_t **) out->planes, out_size, out_samples, + (uint8_t **) in->planes, in_size, in_samples); if (out_samples < 0) return NULL; // error } @@ -338,16 +342,16 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) 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->audio = s->reorder_buffer; + data->planes[0] = s->reorder_buffer; out_samples = avresample_convert(s->avrctx_out, - (uint8_t **) &data->audio, out_size, out_samples, - (uint8_t **) &out->audio, out_size, out_samples); + (uint8_t **) data->planes, out_size, out_samples, + (uint8_t **) out->planes, out_size, out_samples); } #else - reorder_channels(data->audio, s->reorder_out, out->bps, out->nch, out_samples); + reorder_channels(data->planes[0], s->reorder_out, out->bps, out->nch, out_samples); #endif - data->len = out->bps * out_samples * out->nch; + data->samples = out_samples; return data; } diff --git a/audio/filter/af_pan.c b/audio/filter/af_pan.c index b3e31dab98..3c15b8f629 100644 --- a/audio/filter/af_pan.c +++ b/audio/filter/af_pan.c @@ -147,7 +147,7 @@ static int control(struct af_instance* af, int cmd, void* arg) static void uninit(struct af_instance* af) { if(af->data) - free(af->data->audio); + free(af->data->planes[0]); free(af->data); free(af->setup); } @@ -158,9 +158,9 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) struct mp_audio* c = data; // Current working data struct mp_audio* l = af->data; // Local data af_pan_t* s = af->setup; // Setup for this instance - float* in = c->audio; // Input audio data + float* in = c->planes[0]; // Input audio data float* out = NULL; // Output audio data - float* end = in+c->len/4; // End of loop + float* end = in+c->samples*c->nch; // End of loop int nchi = c->nch; // Number of input channels int ncho = l->nch; // Number of output channels register int j,k; @@ -168,7 +168,7 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) return NULL; - out = l->audio; + out = l->planes[0]; // Execute panning // FIXME: Too slow while(in < end){ @@ -184,8 +184,7 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) } // Set output data - c->audio = l->audio; - c->len = c->len / c->nch * l->nch; + c->planes[0] = l->planes[0]; set_channels(c, l->nch); return c; diff --git a/audio/filter/af_scaletempo.c b/audio/filter/af_scaletempo.c index fdcfd5560f..33547bc79c 100644 --- a/audio/filter/af_scaletempo.c +++ b/audio/filter/af_scaletempo.c @@ -84,7 +84,7 @@ typedef struct af_scaletempo_s static int fill_queue(struct af_instance *af, struct mp_audio *data, int offset) { af_scaletempo_t *s = af->priv; - int bytes_in = data->len - offset; + int bytes_in = mp_audio_psize(data) - offset; int offset_unchanged = offset; if (s->bytes_to_slide > 0) { @@ -108,7 +108,7 @@ static int fill_queue(struct af_instance *af, struct mp_audio *data, int offset) int bytes_copy = MPMIN(s->bytes_queue - s->bytes_queued, bytes_in); assert(bytes_copy >= 0); memcpy(s->buf_queue + s->bytes_queued, - (int8_t *)data->audio + offset, bytes_copy); + (int8_t *)data->planes[0] + offset, bytes_copy); s->bytes_queued += bytes_copy; offset += bytes_copy; } @@ -221,23 +221,23 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) } // RESIZE_LOCAL_BUFFER - can't use macro - int max_bytes_out = ((int)(data->len / s->bytes_stride_scaled) + 1) - * s->bytes_stride; - if (max_bytes_out > af->data->len) { + int max_bytes_out = ((int)(mp_audio_psize(data) / + s->bytes_stride_scaled) + 1) * s->bytes_stride; + if (max_bytes_out > mp_audio_psize(af->data)) { mp_msg(MSGT_AFILTER, MSGL_V, "[libaf] Reallocating memory in module %s, " "old len = %i, new len = %i\n", af->info->name, - af->data->len, max_bytes_out); - af->data->audio = realloc(af->data->audio, max_bytes_out); - if (!af->data->audio) { + mp_audio_psize(af->data), max_bytes_out); + af->data->planes[0] = realloc(af->data->planes[0], max_bytes_out); + if (!af->data->planes[0]) { mp_msg(MSGT_AFILTER, MSGL_FATAL, "[libaf] Could not allocate memory\n"); return NULL; } - af->data->len = max_bytes_out; + af->data->samples = max_bytes_out / af->data->sstride; } int offset_in = fill_queue(af, data, 0); - int8_t *pout = af->data->audio; + int8_t *pout = af->data->planes[0]; while (s->bytes_queued >= s->bytes_queue) { int ti; float tf; @@ -271,8 +271,8 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) // after receiving only a part of that input. af->delay = s->bytes_queued - s->bytes_to_slide; - data->audio = af->data->audio; - data->len = pout - (int8_t *)af->data->audio; + data->planes[0] = af->data->planes[0]; + data->samples = (pout - (int8_t *)af->data->planes[0]) / af->data->sstride; return data; } @@ -291,6 +291,7 @@ static int control(struct af_instance *af, int cmd, void *arg) "[scaletempo] %.3f speed * %.3f scale_nominal = %.3f\n", s->speed, s->scale_nominal, s->scale); + mp_audio_force_interleaved_format(data); mp_audio_copy_config(af->data, data); if (s->scale == 1.0) { @@ -456,7 +457,7 @@ static int control(struct af_instance *af, int cmd, void *arg) static void uninit(struct af_instance *af) { af_scaletempo_t *s = af->priv; - free(af->data->audio); + free(af->data->planes[0]); free(af->data); free(s->buf_queue); free(s->buf_overlap); diff --git a/audio/filter/af_sinesuppress.c b/audio/filter/af_sinesuppress.c index b9c86ccfe9..b733caec93 100644 --- a/audio/filter/af_sinesuppress.c +++ b/audio/filter/af_sinesuppress.c @@ -94,8 +94,8 @@ static struct mp_audio* play_s16(struct af_instance* af, struct mp_audio* data) { af_sinesuppress_t *s = af->setup; register int i = 0; - int16_t *a = (int16_t*)data->audio; // Audio data - int len = data->len/2; // Number of samples + int16_t *a = (int16_t*)data->planes[0]; // Audio data + int len = data->samples*data->nch; // Number of samples for (i = 0; i < len; i++) { diff --git a/audio/filter/af_sub.c b/audio/filter/af_sub.c index 7778e80b64..92abd2f0ea 100644 --- a/audio/filter/af_sub.c +++ b/audio/filter/af_sub.c @@ -143,8 +143,8 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) { struct mp_audio* c = data; // Current working data af_sub_t* s = af->setup; // Setup for this instance - float* a = c->audio; // Audio data - int len = c->len/4; // Number of samples in current audio block + float* a = c->planes[0]; // Audio data + int len = c->samples*c->nch; // Number of samples in current audio block int nch = c->nch; // Number of channels int ch = s->ch; // Channel in which to insert the sub audio register int i; diff --git a/audio/filter/af_surround.c b/audio/filter/af_surround.c index e584e6505a..5ee45d126f 100644 --- a/audio/filter/af_surround.c +++ b/audio/filter/af_surround.c @@ -145,7 +145,7 @@ static int control(struct af_instance* af, int cmd, void* arg) static void uninit(struct af_instance* af) { if(af->data) - free(af->data->audio); + free(af->data->planes[0]); free(af->data); free(af->setup); } @@ -165,9 +165,9 @@ static float steering_matrix[][12] = { static struct mp_audio* play(struct af_instance* af, struct mp_audio* data){ af_surround_t* s = (af_surround_t*)af->setup; float* m = steering_matrix[0]; - float* in = data->audio; // Input audio data + float* in = data->planes[0]; // Input audio data float* out = NULL; // Output audio data - float* end = in + data->len / sizeof(float); // Loop end + float* end = in + data->samples * data->nch; int i = s->i; // Filter queue index int ri = s->ri; // Read index for delay queue int wi = s->wi; // Write index for delay queue @@ -175,7 +175,7 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data){ if (AF_OK != RESIZE_LOCAL_BUFFER(af, data)) return NULL; - out = af->data->audio; + out = af->data->planes[0]; while(in < end){ /* Dominance: @@ -237,8 +237,7 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data){ s->i = i; s->ri = ri; s->wi = wi; // Set output data - data->audio = af->data->audio; - data->len *= 2; + data->planes[0] = af->data->planes[0]; mp_audio_set_channels_old(data, af->data->nch); return data; diff --git a/audio/filter/af_sweep.c b/audio/filter/af_sweep.c index 0a140dcb65..daa2891219 100644 --- a/audio/filter/af_sweep.c +++ b/audio/filter/af_sweep.c @@ -67,9 +67,9 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) { af_sweept *s = af->setup; int i, j; - int16_t *in = (int16_t*)data->audio; + int16_t *in = (int16_t*)data->planes[0]; int chans = data->nch; - int in_len = data->len/(2*chans); + int in_len = data->samples; for(i=0; idata, (struct mp_audio *)arg); + mp_audio_force_interleaved_format(af->data); if (s->fast && (((struct mp_audio *)arg)->format != AF_FORMAT_FLOAT_NE)) mp_audio_set_format(af->data, AF_FORMAT_S16_NE); @@ -66,8 +67,8 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) struct priv *s = af->priv; if (af->data->format == AF_FORMAT_S16_NE) { - int16_t *a = c->audio; - int len = c->len / 2; + int16_t *a = c->planes[0]; + int len = c->samples * c->nch; int vol = 256.0 * s->level; if (vol != 256) { for (int i = 0; i < len; i++) { @@ -76,8 +77,8 @@ static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) } } } else if (af->data->format == AF_FORMAT_FLOAT_NE) { - float *a = c->audio; - int len = c->len / 4; + float *a = c->planes[0]; + int len = c->samples * c->nch; float vol = s->level; if (vol != 1.0) { for (int i = 0; i < len; i++) { -- cgit v1.2.3 From bf60281ffb6f47986fa6ef9ee559689be0075050 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 10 Nov 2013 23:15:02 +0100 Subject: audio/out: reject non-interleaved formats No AO can handle these, so it would be a problem if they get added later, and non-interleaved formats get accepted erroneously. Let them gracefully fall back to other formats. Most AOs actually would fall back, but to an unrelated formats. This is covered by this commit too, and if possible they should pick the interleaved variant if a non-interleaved format is requested. --- audio/out/ao_alsa.c | 2 ++ audio/out/ao_coreaudio.c | 2 ++ audio/out/ao_dsound.c | 2 +- audio/out/ao_lavc.c | 1 + audio/out/ao_null.c | 2 ++ audio/out/ao_oss.c | 2 ++ audio/out/ao_pcm.c | 3 +++ audio/out/ao_portaudio.c | 2 ++ audio/out/ao_pulse.c | 2 ++ audio/out/ao_rsound.c | 2 ++ audio/out/ao_sdl.c | 2 ++ audio/out/ao_sndio.c | 3 +++ audio/out/ao_wasapi.c | 1 + 13 files changed, 25 insertions(+), 1 deletion(-) diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index 5816ee5f5f..0d1c589e34 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -436,6 +436,8 @@ static int init(struct ao *ao) (p->alsa, alsa_hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); CHECK_ALSA_ERROR("Unable to set access type"); + ao->format = af_fmt_from_planar(ao->format); + p->alsa_fmt = find_alsa_format(ao->format); if (p->alsa_fmt == SND_PCM_FORMAT_UNKNOWN) { p->alsa_fmt = SND_PCM_FORMAT_S16; diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index da526ada20..4823eb43e1 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -285,6 +285,8 @@ static int init(struct ao *ao) // Save selected device id p->device = selected_device; + ao->format = af_fmt_from_planar(ao->format); + bool supports_digital = false; /* Probe whether device support S/PDIF stream output if input is AC3 stream. */ if (AF_FORMAT_IS_AC3(ao->format)) { diff --git a/audio/out/ao_dsound.c b/audio/out/ao_dsound.c index 464947c0dc..58812d80e6 100644 --- a/audio/out/ao_dsound.c +++ b/audio/out/ao_dsound.c @@ -388,7 +388,7 @@ static int init(struct ao *ao) WAVEFORMATEXTENSIBLE wformat; DSBUFFERDESC dsbpridesc; DSBUFFERDESC dsbdesc; - int format = ao->format; + int format = af_fmt_from_planar(ao->format); int rate = ao->samplerate; if (AF_FORMAT_IS_AC3(format)) diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c index 4364b9054d..b849f9b2b4 100644 --- a/audio/out/ao_lavc.c +++ b/audio/out/ao_lavc.c @@ -105,6 +105,7 @@ static int init(struct ao *ao) ac->stream->codec->channel_layout = mp_chmap_to_lavc(&ao->channels); ac->stream->codec->sample_fmt = AV_SAMPLE_FMT_NONE; + ao->format = af_fmt_from_planar(ao->format); { // first check if the selected format is somewhere in the list of diff --git a/audio/out/ao_null.c b/audio/out/ao_null.c index ff6b12a1a6..75e812b238 100644 --- a/audio/out/ao_null.c +++ b/audio/out/ao_null.c @@ -51,6 +51,8 @@ static int init(struct ao *ao) struct priv *priv = talloc_zero(ao, struct priv); ao->priv = priv; + ao->format = af_fmt_from_planar(ao->format); + struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_any(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c index db9847851d..a97424c1cb 100644 --- a/audio/out/ao_oss.c +++ b/audio/out/ao_oss.c @@ -261,6 +261,8 @@ static int init(struct ao *ao) fcntl(p->audio_fd, F_SETFD, FD_CLOEXEC); #endif + ao->format = af_fmt_from_planar(ao->format); + if (AF_FORMAT_IS_AC3(ao->format)) { ioctl(p->audio_fd, SNDCTL_DSP_SPEED, &ao->samplerate); } diff --git a/audio/out/ao_pcm.c b/audio/out/ao_pcm.c index f7d793700d..e94e6b569a 100644 --- a/audio/out/ao_pcm.c +++ b/audio/out/ao_pcm.c @@ -118,6 +118,9 @@ static int init(struct ao *ao) if (!priv->outputfilename) priv->outputfilename = talloc_strdup(priv, priv->waveheader ? "audiodump.wav" : "audiodump.pcm"); + + ao->format = af_fmt_from_planar(ao->format); + if (priv->waveheader) { // WAV files must have one of the following formats diff --git a/audio/out/ao_portaudio.c b/audio/out/ao_portaudio.c index 8b235f8806..d75fad0aca 100644 --- a/audio/out/ao_portaudio.c +++ b/audio/out/ao_portaudio.c @@ -242,6 +242,8 @@ static int init(struct ao *ao) = Pa_GetDeviceInfo(pa_device)->defaultHighOutputLatency, }; + ao->format = af_fmt_from_planar(ao->format); + const struct format_map *fmt = format_maps; while (fmt->pa_format) { if (fmt->mp_format == ao->format) { diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c index a4da2a179b..1d7fcdd382 100644 --- a/audio/out/ao_pulse.c +++ b/audio/out/ao_pulse.c @@ -286,6 +286,8 @@ static int init(struct ao *ao) ss.channels = ao->channels.num; ss.rate = ao->samplerate; + ao->format = af_fmt_from_planar(ao->format); + const struct format_map *fmt_map = format_maps; while (fmt_map->mp_format != ao->format) { if (fmt_map->mp_format == AF_FORMAT_UNKNOWN) { diff --git a/audio/out/ao_rsound.c b/audio/out/ao_rsound.c index 162fb21feb..95fadf7188 100644 --- a/audio/out/ao_rsound.c +++ b/audio/out/ao_rsound.c @@ -114,6 +114,8 @@ static int init(struct ao *ao) rsd_set_param(priv->rd, RSD_SAMPLERATE, &ao->samplerate); rsd_set_param(priv->rd, RSD_CHANNELS, &ao->channels.num); + ao->format = af_fmt_from_planar(ao->format); + int rsd_format = set_format(ao); rsd_set_param(priv->rd, RSD_FORMAT, &rsd_format); diff --git a/audio/out/ao_sdl.c b/audio/out/ao_sdl.c index a42c0812cb..d95a82615b 100644 --- a/audio/out/ao_sdl.c +++ b/audio/out/ao_sdl.c @@ -144,6 +144,8 @@ static int init(struct ao *ao) return -1; } + ao->format = af_fmt_from_planar(ao->format); + SDL_AudioSpec desired, obtained; switch (ao->format) { diff --git a/audio/out/ao_sndio.c b/audio/out/ao_sndio.c index ab9eaf8197..1786c0158d 100644 --- a/audio/out/ao_sndio.c +++ b/audio/out/ao_sndio.c @@ -130,6 +130,9 @@ static int init(struct ao *ao) MP_ERR(ao, "can't open sndio %s\n", p->dev); goto error; } + + ao->format = af_fmt_from_planar(ao->format); + sio_initpar(&p->par); for (i = 0, ap = af_to_par;; i++, ap++) { if (i == sizeof(af_to_par) / sizeof(struct af_to_par)) { diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index c605e1cd5d..5d9f33278c 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -1231,6 +1231,7 @@ static void uninit(struct ao *ao, bool immed) static int init(struct ao *ao) { mp_msg(MSGT_AO, MSGL_V, "ao-wasapi: init!\n"); + ao->format = af_fmt_from_planar(ao->format); struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_waveext(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) -- cgit v1.2.3 From 45d1510e4e9fcaeb5781c78f7927555b569079cd Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 10 Nov 2013 23:17:04 +0100 Subject: af_lavrresample: add support for non-interleaved audio --- audio/filter/af_lavrresample.c | 72 ++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c index a6abd32aed..8c7a7543fa 100644 --- a/audio/filter/af_lavrresample.c +++ b/audio/filter/af_lavrresample.c @@ -24,6 +24,8 @@ #include #include #include +#include + #include #include #include @@ -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++) { +