From b2d4b5ee43206f8c4491b3af1c24fedd35dbdc31 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 10 Nov 2013 23:10:16 +0100 Subject: [PATCH] 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);