mirror of https://github.com/mpv-player/mpv
audio: drop swapped-endian audio formats
Until now, the audio chain could handle both little endian and big endian formats. This actually doesn't make much sense, since the audio API and the HW will most likely prefer native formats. Or at the very least, it should be trivial for audio drivers to do the byte swapping themselves. From now on, the audio chain contains native-endian formats only. All AOs and some filters are adjusted. af_convertsignendian.c is now wrongly named, but the filter name is adjusted. In some cases, the audio infrastructure was reused on the demuxer side, but that is relatively easy to rectify. This is a quite intrusive and radical change. It's possible that it will break some things (especially if they're obscure or not Linux), so watch out for regressions. It's probably still better to do it the bulldozer way, since slow transition and researching foreign platforms would take a lot of time and effort.
This commit is contained in:
parent
5b5a3d0c46
commit
b745c2d005
|
@ -265,9 +265,8 @@ Available filters are:
|
|||
Filter for internal use only. Converts between 24-bit and 32-bit sample
|
||||
formats.
|
||||
|
||||
``convertsignendian``
|
||||
Filter for internal use only. Converts between signed/unsigned formats
|
||||
and formats with different endian.
|
||||
``convertsign``
|
||||
Filter for internal use only. Converts between signed/unsigned formats.
|
||||
|
||||
``volume[=<volumedb>[:...]]``
|
||||
Implements software volume control. Use this filter with caution since it
|
||||
|
|
|
@ -96,25 +96,30 @@ static const struct pcm_map tag_map[] = {
|
|||
|
||||
// For demux_rawaudio.c; needed because ffmpeg doesn't have these sample
|
||||
// formats natively.
|
||||
static const struct pcm_map af_map[] = {
|
||||
static const struct pcm_map af_map_le[] = {
|
||||
{AF_FORMAT_U8, {"pcm_u8"}},
|
||||
{AF_FORMAT_S8, {"pcm_u8"}},
|
||||
{AF_FORMAT_U16_LE, {"pcm_u16le"}},
|
||||
{AF_FORMAT_U16_BE, {"pcm_u16be"}},
|
||||
{AF_FORMAT_S16_LE, {"pcm_s16le"}},
|
||||
{AF_FORMAT_S16_BE, {"pcm_s16be"}},
|
||||
{AF_FORMAT_U24_LE, {"pcm_u24le"}},
|
||||
{AF_FORMAT_U24_BE, {"pcm_u24be"}},
|
||||
{AF_FORMAT_S24_LE, {"pcm_s24le"}},
|
||||
{AF_FORMAT_S24_BE, {"pcm_s24be"}},
|
||||
{AF_FORMAT_U32_LE, {"pcm_u32le"}},
|
||||
{AF_FORMAT_U32_BE, {"pcm_u32be"}},
|
||||
{AF_FORMAT_S32_LE, {"pcm_s32le"}},
|
||||
{AF_FORMAT_S32_BE, {"pcm_s32be"}},
|
||||
{AF_FORMAT_FLOAT_LE, {"pcm_f32le"}},
|
||||
{AF_FORMAT_FLOAT_BE, {"pcm_f32be"}},
|
||||
{AF_FORMAT_DOUBLE_LE, {"pcm_f64le"}},
|
||||
{AF_FORMAT_DOUBLE_BE, {"pcm_f64be"}},
|
||||
{AF_FORMAT_U16, {"pcm_u16le"}},
|
||||
{AF_FORMAT_S16, {"pcm_s16le"}},
|
||||
{AF_FORMAT_U24, {"pcm_u24le"}},
|
||||
{AF_FORMAT_S24, {"pcm_s24le"}},
|
||||
{AF_FORMAT_U32, {"pcm_u32le"}},
|
||||
{AF_FORMAT_S32, {"pcm_s32le"}},
|
||||
{AF_FORMAT_FLOAT, {"pcm_f32le"}},
|
||||
{AF_FORMAT_DOUBLE, {"pcm_f64le"}},
|
||||
{-1},
|
||||
};
|
||||
static const struct pcm_map af_map_be[] = {
|
||||
{AF_FORMAT_U8, {"pcm_u8"}},
|
||||
{AF_FORMAT_S8, {"pcm_u8"}},
|
||||
{AF_FORMAT_U16, {"pcm_u16be"}},
|
||||
{AF_FORMAT_S16, {"pcm_s16be"}},
|
||||
{AF_FORMAT_U24, {"pcm_u24be"}},
|
||||
{AF_FORMAT_S24, {"pcm_s24be"}},
|
||||
{AF_FORMAT_U32, {"pcm_u32be"}},
|
||||
{AF_FORMAT_S32, {"pcm_s32be"}},
|
||||
{AF_FORMAT_FLOAT, {"pcm_f32be"}},
|
||||
{AF_FORMAT_DOUBLE, {"pcm_f64be"}},
|
||||
{-1},
|
||||
};
|
||||
|
||||
|
@ -198,7 +203,8 @@ static int init(struct dec_audio *da, const char *decoder)
|
|||
decoder = find_pcm_decoder(tag_map, sh->format,
|
||||
sh_audio->wf->wBitsPerSample);
|
||||
} else if (sh_audio->wf && strcmp(decoder, "mp-pcm") == 0) {
|
||||
decoder = find_pcm_decoder(af_map, sh->format, 0);
|
||||
const struct pcm_map *map = sh_audio->big_endian ? af_map_be : af_map_le;
|
||||
decoder = find_pcm_decoder(map, sh->format, 0);
|
||||
ctx->force_channel_map = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,20 +48,12 @@ static int filter_##name(struct af_instance *af, struct mp_audio *data, int f) \
|
|||
}
|
||||
|
||||
FILTER(f, float)
|
||||
FILTER(fbe, float)
|
||||
FILTER(fle, float)
|
||||
FILTER(s32be, int32_t)
|
||||
FILTER(u32be, uint32_t)
|
||||
FILTER(s32le, int32_t)
|
||||
FILTER(u32le, uint32_t)
|
||||
FILTER(s24be, bs2b_int24_t)
|
||||
FILTER(u24be, bs2b_uint24_t)
|
||||
FILTER(s24le, bs2b_int24_t)
|
||||
FILTER(u24le, bs2b_uint24_t)
|
||||
FILTER(s16be, int16_t)
|
||||
FILTER(u16be, uint16_t)
|
||||
FILTER(s16le, int16_t)
|
||||
FILTER(u16le, uint16_t)
|
||||
FILTER(s32, int32_t)
|
||||
FILTER(u32, uint32_t)
|
||||
FILTER(s24, bs2b_int24_t)
|
||||
FILTER(u24, bs2b_uint24_t)
|
||||
FILTER(s16, int16_t)
|
||||
FILTER(u16, uint16_t)
|
||||
FILTER(s8, int8_t)
|
||||
FILTER(u8, uint8_t)
|
||||
|
||||
|
@ -85,47 +77,26 @@ static int control(struct af_instance *af, int cmd, void *arg)
|
|||
/* check for formats supported by libbs2b
|
||||
and assign corresponding handlers */
|
||||
switch (format) {
|
||||
case AF_FORMAT_FLOAT_BE:
|
||||
af->filter = filter_fbe;
|
||||
case AF_FORMAT_FLOAT:
|
||||
af->filter = filter_f;
|
||||
break;
|
||||
case AF_FORMAT_FLOAT_LE:
|
||||
af->filter = filter_fle;
|
||||
case AF_FORMAT_S32:
|
||||
af->filter = filter_s32;
|
||||
break;
|
||||
case AF_FORMAT_S32_BE:
|
||||
af->filter = filter_s32be;
|
||||
case AF_FORMAT_U32:
|
||||
af->filter = filter_u32;
|
||||
break;
|
||||
case AF_FORMAT_U32_BE:
|
||||
af->filter = filter_u32be;
|
||||
case AF_FORMAT_S24:
|
||||
af->filter = filter_s24;
|
||||
break;
|
||||
case AF_FORMAT_S32_LE:
|
||||
af->filter = filter_s32le;
|
||||
case AF_FORMAT_U24:
|
||||
af->filter = filter_u24;
|
||||
break;
|
||||
case AF_FORMAT_U32_LE:
|
||||
af->filter = filter_u32le;
|
||||
case AF_FORMAT_S16:
|
||||
af->filter = filter_s16;
|
||||
break;
|
||||
case AF_FORMAT_S24_BE:
|
||||
af->filter = filter_s24be;
|
||||
break;
|
||||
case AF_FORMAT_U24_BE:
|
||||
af->filter = filter_u24be;
|
||||
break;
|
||||
case AF_FORMAT_S24_LE:
|
||||
af->filter = filter_s24le;
|
||||
break;
|
||||
case AF_FORMAT_U24_LE:
|
||||
af->filter = filter_u24le;
|
||||
break;
|
||||
case AF_FORMAT_S16_BE:
|
||||
af->filter = filter_s16be;
|
||||
break;
|
||||
case AF_FORMAT_U16_BE:
|
||||
af->filter = filter_u16be;
|
||||
break;
|
||||
case AF_FORMAT_S16_LE:
|
||||
af->filter = filter_s16le;
|
||||
break;
|
||||
case AF_FORMAT_U16_LE:
|
||||
af->filter = filter_u16le;
|
||||
case AF_FORMAT_U16:
|
||||
af->filter = filter_u16;
|
||||
break;
|
||||
case AF_FORMAT_S8:
|
||||
af->filter = filter_s8;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "audio/format.h"
|
||||
#include "af.h"
|
||||
#include "osdep/endian.h"
|
||||
|
||||
static bool test_conversion(int src_format, int dst_format)
|
||||
{
|
||||
|
|
|
@ -20,21 +20,16 @@
|
|||
|
||||
#include "af.h"
|
||||
#include "audio/format.h"
|
||||
#include "osdep/mpbswap.h"
|
||||
#include "osdep/endian.h"
|
||||
|
||||
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.
|
||||
if (src_noend == dst_noend)
|
||||
return true;
|
||||
if (((src_noend & ~AF_FORMAT_SIGN_MASK) ==
|
||||
(dst_noend & ~AF_FORMAT_SIGN_MASK)) &&
|
||||
((src_noend & AF_FORMAT_POINT_MASK) == AF_FORMAT_I))
|
||||
if (((src_format & ~AF_FORMAT_SIGN_MASK) ==
|
||||
(dst_format & ~AF_FORMAT_SIGN_MASK)) &&
|
||||
((src_format & AF_FORMAT_POINT_MASK) == AF_FORMAT_I))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -63,34 +58,11 @@ static int control(struct af_instance *af, int cmd, void *arg)
|
|||
return AF_UNKNOWN;
|
||||
}
|
||||
|
||||
static void endian(void *data, int len, int bps)
|
||||
{
|
||||
switch (bps) {
|
||||
case 2:
|
||||
for (int i = 0; i < len; i++) {
|
||||
((uint16_t*)data)[i] = bswap_16(((uint16_t *)data)[i]);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for(int i = 0; i < len; i++) {
|
||||
uint8_t s = ((uint8_t *)data)[3 * i];
|
||||
((uint8_t *)data)[3 * i] = ((uint8_t *)data)[3 * i + 2];
|
||||
((uint8_t *)data)[3 * i + 2] = s;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for(int i = 0; i < len; i++) {
|
||||
((uint32_t*)data)[i] = bswap_32(((uint32_t *)data)[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void si2us(void *data, int len, int bps, bool le)
|
||||
static void si2us(void *data, int len, int bps)
|
||||
{
|
||||
ptrdiff_t i = -(len * bps);
|
||||
uint8_t *p = &((uint8_t *)data)[len * bps];
|
||||
if (le && bps > 1)
|
||||
if (BYTE_ORDER == LITTLE_ENDIAN && bps > 1)
|
||||
p += bps - 1;
|
||||
if (len <= 0)
|
||||
return;
|
||||
|
@ -105,12 +77,8 @@ static int filter(struct af_instance *af, struct mp_audio *data, int flags)
|
|||
int outfmt = af->data->format;
|
||||
size_t len = data->samples * data->nch;
|
||||
|
||||
if ((infmt & AF_FORMAT_END_MASK) != (outfmt & AF_FORMAT_END_MASK))
|
||||
endian(data->planes[0], len, data->bps);
|
||||
|
||||
if ((infmt & AF_FORMAT_SIGN_MASK) != (outfmt & AF_FORMAT_SIGN_MASK))
|
||||
si2us(data->planes[0], len, data->bps,
|
||||
(outfmt & AF_FORMAT_END_MASK) == AF_FORMAT_LE);
|
||||
si2us(data->planes[0], len, data->bps);
|
||||
|
||||
mp_audio_set_format(data, outfmt);
|
||||
return 0;
|
||||
|
@ -124,8 +92,8 @@ static int af_open(struct af_instance *af)
|
|||
}
|
||||
|
||||
const struct af_info af_info_convertsignendian = {
|
||||
.info = "Convert between sample format sign/endian",
|
||||
.name = "convertsignendian",
|
||||
.info = "Convert between sample format sign",
|
||||
.name = "convertsign",
|
||||
.open = af_open,
|
||||
.test_conversion = test_conversion,
|
||||
};
|
||||
|
|
|
@ -109,35 +109,27 @@ bool af_fmt_is_planar(int format)
|
|||
return !!(format & AF_FORMAT_PLANAR);
|
||||
}
|
||||
|
||||
#define FMT(string, id) \
|
||||
{string, id},
|
||||
|
||||
#define FMT_ENDIAN(string, id) \
|
||||
{string, id}, \
|
||||
{string "le", MP_CONCAT(id, _LE)}, \
|
||||
{string "be", MP_CONCAT(id, _BE)}, \
|
||||
|
||||
const struct af_fmt_entry af_fmtstr_table[] = {
|
||||
FMT("mpeg2", AF_FORMAT_MPEG2)
|
||||
FMT("ac3", AF_FORMAT_AC3)
|
||||
FMT("iec61937", AF_FORMAT_IEC61937)
|
||||
{"mpeg2", AF_FORMAT_MPEG2},
|
||||
{"ac3", AF_FORMAT_AC3},
|
||||
{"iec61937", AF_FORMAT_IEC61937},
|
||||
|
||||
FMT("u8", AF_FORMAT_U8)
|
||||
FMT("s8", AF_FORMAT_S8)
|
||||
FMT_ENDIAN("u16", AF_FORMAT_U16)
|
||||
FMT_ENDIAN("s16", AF_FORMAT_S16)
|
||||
FMT_ENDIAN("u24", AF_FORMAT_U24)
|
||||
FMT_ENDIAN("s24", AF_FORMAT_S24)
|
||||
FMT_ENDIAN("u32", AF_FORMAT_U32)
|
||||
FMT_ENDIAN("s32", AF_FORMAT_S32)
|
||||
FMT_ENDIAN("float", AF_FORMAT_FLOAT)
|
||||
FMT_ENDIAN("double", AF_FORMAT_DOUBLE)
|
||||
{"u8", AF_FORMAT_U8},
|
||||
{"s8", AF_FORMAT_S8},
|
||||
{"u16", AF_FORMAT_U16},
|
||||
{"s16", AF_FORMAT_S16},
|
||||
{"u24", AF_FORMAT_U24},
|
||||
{"s24", AF_FORMAT_S24},
|
||||
{"u32", AF_FORMAT_U32},
|
||||
{"s32", AF_FORMAT_S32},
|
||||
{"float", AF_FORMAT_FLOAT},
|
||||
{"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)
|
||||
{"u8p", AF_FORMAT_U8P},
|
||||
{"s16p", AF_FORMAT_S16P},
|
||||
{"s32p", AF_FORMAT_S32P},
|
||||
{"floatp", AF_FORMAT_FLOATP},
|
||||
{"doublep", AF_FORMAT_DOUBLEP},
|
||||
|
||||
{0}
|
||||
};
|
||||
|
@ -199,17 +191,12 @@ int af_format_conversion_score(int dst_format, int src_format)
|
|||
return INT_MIN;
|
||||
if (dst_format == src_format)
|
||||
return 1024;
|
||||
// Just endian swapping (separate because it works for special formats)
|
||||
if ((dst_format & ~AF_FORMAT_END_MASK) == (src_format & ~AF_FORMAT_END_MASK))
|
||||
return 1024 - 2;
|
||||
// Can't be normally converted
|
||||
if (AF_FORMAT_IS_SPECIAL(dst_format) || AF_FORMAT_IS_SPECIAL(src_format))
|
||||
return INT_MIN;
|
||||
int score = 1024;
|
||||
if (FMT_DIFF(AF_FORMAT_INTERLEAVING_MASK, dst_format, src_format))
|
||||
score -= 1; // has to (de-)planarize
|
||||
if (FMT_DIFF(AF_FORMAT_END_MASK, dst_format, src_format))
|
||||
score -= 2; // has to swap endian
|
||||
if (FMT_DIFF(AF_FORMAT_SIGN_MASK, dst_format, src_format))
|
||||
score -= 4; // has to swap sign
|
||||
if (FMT_DIFF(AF_FORMAT_POINT_MASK, dst_format, src_format)) {
|
||||
|
|
|
@ -25,22 +25,8 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "osdep/endian.h"
|
||||
#include "misc/bstr.h"
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define AF_SELECT_LE_BE(LE, BE) BE
|
||||
#else
|
||||
#define AF_SELECT_LE_BE(LE, BE) LE
|
||||
#endif
|
||||
|
||||
// Endianness
|
||||
#define AF_FORMAT_BE (0<<0) // Big Endian
|
||||
#define AF_FORMAT_LE (1<<0) // Little Endian
|
||||
#define AF_FORMAT_END_MASK (1<<0)
|
||||
|
||||
#define AF_FORMAT_NE AF_SELECT_LE_BE(AF_FORMAT_LE, AF_FORMAT_BE)
|
||||
|
||||
// Signed/unsigned
|
||||
#define AF_FORMAT_SI (0<<1) // Signed
|
||||
#define AF_FORMAT_US (1<<1) // Unsigned
|
||||
|
@ -80,48 +66,28 @@
|
|||
enum af_format {
|
||||
AF_FORMAT_UNKNOWN = 0,
|
||||
|
||||
AF_FORMAT_U8 = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_8BIT|AF_FORMAT_NE),
|
||||
AF_FORMAT_S8 = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_8BIT|AF_FORMAT_NE),
|
||||
AF_FORMAT_U16_LE = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_16BIT|AF_FORMAT_LE),
|
||||
AF_FORMAT_U16_BE = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_16BIT|AF_FORMAT_BE),
|
||||
AF_FORMAT_S16_LE = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_16BIT|AF_FORMAT_LE),
|
||||
AF_FORMAT_S16_BE = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_16BIT|AF_FORMAT_BE),
|
||||
AF_FORMAT_U24_LE = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_24BIT|AF_FORMAT_LE),
|
||||
AF_FORMAT_U24_BE = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_24BIT|AF_FORMAT_BE),
|
||||
AF_FORMAT_S24_LE = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_24BIT|AF_FORMAT_LE),
|
||||
AF_FORMAT_S24_BE = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_24BIT|AF_FORMAT_BE),
|
||||
AF_FORMAT_U32_LE = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_32BIT|AF_FORMAT_LE),
|
||||
AF_FORMAT_U32_BE = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_32BIT|AF_FORMAT_BE),
|
||||
AF_FORMAT_S32_LE = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_32BIT|AF_FORMAT_LE),
|
||||
AF_FORMAT_S32_BE = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_32BIT|AF_FORMAT_BE),
|
||||
AF_FORMAT_U8 = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_8BIT),
|
||||
AF_FORMAT_S8 = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_8BIT),
|
||||
AF_FORMAT_U16 = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_16BIT),
|
||||
AF_FORMAT_S16 = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_16BIT),
|
||||
AF_FORMAT_U24 = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_24BIT),
|
||||
AF_FORMAT_S24 = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_24BIT),
|
||||
AF_FORMAT_U32 = (AF_FORMAT_I|AF_FORMAT_US|AF_FORMAT_32BIT),
|
||||
AF_FORMAT_S32 = (AF_FORMAT_I|AF_FORMAT_SI|AF_FORMAT_32BIT),
|
||||
|
||||
AF_FORMAT_FLOAT_LE = (AF_FORMAT_F|AF_FORMAT_32BIT|AF_FORMAT_LE),
|
||||
AF_FORMAT_FLOAT_BE = (AF_FORMAT_F|AF_FORMAT_32BIT|AF_FORMAT_BE),
|
||||
AF_FORMAT_FLOAT = (AF_FORMAT_F|AF_FORMAT_32BIT),
|
||||
AF_FORMAT_DOUBLE = (AF_FORMAT_F|AF_FORMAT_64BIT),
|
||||
|
||||
AF_FORMAT_DOUBLE_LE = (AF_FORMAT_F|AF_FORMAT_64BIT|AF_FORMAT_LE),
|
||||
AF_FORMAT_DOUBLE_BE = (AF_FORMAT_F|AF_FORMAT_64BIT|AF_FORMAT_BE),
|
||||
|
||||
AF_FORMAT_AC3 = (AF_FORMAT_S_AC3|AF_FORMAT_16BIT|AF_FORMAT_LE),
|
||||
AF_FORMAT_IEC61937 = (AF_FORMAT_S_IEC61937|AF_FORMAT_16BIT|AF_FORMAT_LE),
|
||||
AF_FORMAT_AC3 = (AF_FORMAT_S_AC3|AF_FORMAT_16BIT),
|
||||
AF_FORMAT_IEC61937 = (AF_FORMAT_S_IEC61937|AF_FORMAT_16BIT),
|
||||
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_SI|AF_FORMAT_32BIT|AF_FORMAT_NE),
|
||||
AF_FORMAT_FLOATP = (AF_FLTP|AF_FORMAT_32BIT|AF_FORMAT_NE),
|
||||
AF_FORMAT_DOUBLEP = (AF_FLTP|AF_FORMAT_64BIT|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),
|
||||
AF_FORMAT_U24 = AF_SELECT_LE_BE(AF_FORMAT_U24_LE, AF_FORMAT_U24_BE),
|
||||
AF_FORMAT_S24 = AF_SELECT_LE_BE(AF_FORMAT_S24_LE, AF_FORMAT_S24_BE),
|
||||
AF_FORMAT_U32 = AF_SELECT_LE_BE(AF_FORMAT_U32_LE, AF_FORMAT_U32_BE),
|
||||
AF_FORMAT_S32 = AF_SELECT_LE_BE(AF_FORMAT_S32_LE, AF_FORMAT_S32_BE),
|
||||
|
||||
AF_FORMAT_FLOAT = AF_SELECT_LE_BE(AF_FORMAT_FLOAT_LE, AF_FORMAT_FLOAT_BE),
|
||||
AF_FORMAT_DOUBLE = AF_SELECT_LE_BE(AF_FORMAT_DOUBLE_LE, AF_FORMAT_DOUBLE_BE),
|
||||
AF_FORMAT_U8P = (AF_INTP|AF_FORMAT_US|AF_FORMAT_8BIT),
|
||||
AF_FORMAT_S16P = (AF_INTP|AF_FORMAT_SI|AF_FORMAT_16BIT),
|
||||
AF_FORMAT_S32P = (AF_INTP|AF_FORMAT_SI|AF_FORMAT_32BIT),
|
||||
AF_FORMAT_FLOATP = (AF_FLTP|AF_FORMAT_32BIT),
|
||||
AF_FORMAT_DOUBLEP = (AF_FLTP|AF_FORMAT_64BIT),
|
||||
};
|
||||
|
||||
#define AF_FORMAT_IS_AC3(fmt) \
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "options/options.h"
|
||||
#include "options/m_option.h"
|
||||
#include "common/msg.h"
|
||||
#include "osdep/endian.h"
|
||||
|
||||
#define ALSA_PCM_NEW_HW_PARAMS_API
|
||||
#define ALSA_PCM_NEW_SW_PARAMS_API
|
||||
|
@ -208,22 +209,17 @@ alsa_error:
|
|||
static const int mp_to_alsa_format[][2] = {
|
||||
{AF_FORMAT_S8, SND_PCM_FORMAT_S8},
|
||||
{AF_FORMAT_U8, SND_PCM_FORMAT_U8},
|
||||
{AF_FORMAT_U16_LE, SND_PCM_FORMAT_U16_LE},
|
||||
{AF_FORMAT_U16_BE, SND_PCM_FORMAT_U16_BE},
|
||||
{AF_FORMAT_S16_LE, SND_PCM_FORMAT_S16_LE},
|
||||
{AF_FORMAT_S16_BE, SND_PCM_FORMAT_S16_BE},
|
||||
{AF_FORMAT_U32_LE, SND_PCM_FORMAT_U32_LE},
|
||||
{AF_FORMAT_U32_BE, SND_PCM_FORMAT_U32_BE},
|
||||
{AF_FORMAT_S32_LE, SND_PCM_FORMAT_S32_LE},
|
||||
{AF_FORMAT_S32_BE, SND_PCM_FORMAT_S32_BE},
|
||||
{AF_FORMAT_U24_LE, SND_PCM_FORMAT_U24_3LE},
|
||||
{AF_FORMAT_U24_BE, SND_PCM_FORMAT_U24_3BE},
|
||||
{AF_FORMAT_S24_LE, SND_PCM_FORMAT_S24_3LE},
|
||||
{AF_FORMAT_S24_BE, SND_PCM_FORMAT_S24_3BE},
|
||||
{AF_FORMAT_FLOAT_LE, SND_PCM_FORMAT_FLOAT_LE},
|
||||
{AF_FORMAT_FLOAT_BE, SND_PCM_FORMAT_FLOAT_BE},
|
||||
{AF_FORMAT_AC3, SND_PCM_FORMAT_S16_LE},
|
||||
{AF_FORMAT_IEC61937, SND_PCM_FORMAT_S16_LE},
|
||||
{AF_FORMAT_U16, SND_PCM_FORMAT_U16},
|
||||
{AF_FORMAT_S16, SND_PCM_FORMAT_S16},
|
||||
{AF_FORMAT_U32, SND_PCM_FORMAT_U32},
|
||||
{AF_FORMAT_S32, SND_PCM_FORMAT_S32},
|
||||
{AF_FORMAT_U24,
|
||||
MP_SELECT_LE_BE(SND_PCM_FORMAT_U24_3LE, SND_PCM_FORMAT_U24_3BE)},
|
||||
{AF_FORMAT_S24,
|
||||
MP_SELECT_LE_BE(SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_S24_3BE)},
|
||||
{AF_FORMAT_FLOAT, SND_PCM_FORMAT_FLOAT},
|
||||
{AF_FORMAT_AC3, SND_PCM_FORMAT_S16},
|
||||
{AF_FORMAT_IEC61937, SND_PCM_FORMAT_S16},
|
||||
{AF_FORMAT_MPEG2, SND_PCM_FORMAT_MPEG},
|
||||
{AF_FORMAT_UNKNOWN, SND_PCM_FORMAT_UNKNOWN},
|
||||
};
|
||||
|
@ -417,13 +413,13 @@ static int init(struct ao *ao)
|
|||
if (err < 0) {
|
||||
MP_INFO(ao, "Format %s is not supported by hardware, trying default.\n",
|
||||
af_fmt_to_str(ao->format));
|
||||
p->alsa_fmt = SND_PCM_FORMAT_S16_LE;
|
||||
p->alsa_fmt = SND_PCM_FORMAT_S16;
|
||||
if (AF_FORMAT_IS_AC3(ao->format))
|
||||
ao->format = AF_FORMAT_AC3;
|
||||
else if (AF_FORMAT_IS_IEC61937(ao->format))
|
||||
ao->format = AF_FORMAT_IEC61937;
|
||||
else
|
||||
ao->format = AF_FORMAT_S16_LE;
|
||||
ao->format = AF_FORMAT_S16;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_format(p->alsa, alsa_hwparams, p->alsa_fmt);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "audio/out/ao_coreaudio_utils.h"
|
||||
#include "audio/out/ao_coreaudio_properties.h"
|
||||
#include "osdep/timer.h"
|
||||
#include "osdep/endian.h"
|
||||
#include "audio/format.h"
|
||||
|
||||
void ca_print_device_list(struct ao *ao)
|
||||
|
@ -142,7 +143,7 @@ void ca_fill_asbd(struct ao *ao, AudioStreamBasicDescription *asbd)
|
|||
if ((ao->format & AF_FORMAT_SIGN_MASK) == AF_FORMAT_SI)
|
||||
asbd->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
|
||||
|
||||
if ((ao->format & AF_FORMAT_END_MASK) == AF_FORMAT_BE)
|
||||
if (BYTE_ORDER == BIG_ENDIAN)
|
||||
asbd->mFormatFlags |= kAudioFormatFlagIsBigEndian;
|
||||
|
||||
asbd->mFramesPerPacket = 1;
|
||||
|
|
|
@ -392,14 +392,14 @@ static int init(struct ao *ao)
|
|||
}
|
||||
switch (format) {
|
||||
case AF_FORMAT_AC3:
|
||||
case AF_FORMAT_S24_LE:
|
||||
case AF_FORMAT_S16_LE:
|
||||
case AF_FORMAT_S24:
|
||||
case AF_FORMAT_S16:
|
||||
case AF_FORMAT_U8:
|
||||
break;
|
||||
default:
|
||||
MP_VERBOSE(ao, "format %s not supported defaulting to Signed 16-bit Little-Endian\n",
|
||||
af_fmt_to_str(format));
|
||||
format = AF_FORMAT_S16_LE;
|
||||
format = AF_FORMAT_S16;
|
||||
}
|
||||
//set our audio parameters
|
||||
ao->samplerate = rate;
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "options/options.h"
|
||||
#include "common/msg.h"
|
||||
#include "osdep/timer.h"
|
||||
#include "osdep/endian.h"
|
||||
|
||||
#if HAVE_SYS_SOUNDCARD_H
|
||||
#include <sys/soundcard.h>
|
||||
|
@ -89,39 +90,46 @@ static const struct mp_chmap oss_layouts[MP_NUM_CHANNELS + 1] = {
|
|||
MP_CHMAP8(FL, FR, BL, BR, FC, LFE, SL, SR), // 7.1
|
||||
};
|
||||
|
||||
#if !defined(AFMT_S16_NE) && defined(AFMT_S16_LE) && defined(AFMT_S16_BE)
|
||||
#define AFMT_S16_NE MP_SELECT_LE_BE(AFMT_S16_LE, AFMT_S16_BE)
|
||||
#endif
|
||||
|
||||
#if !defined(AFMT_U16_NE) && defined(AFMT_U16_LE) && defined(AFMT_U16_BE)
|
||||
#define AFMT_U16_NE MP_SELECT_LE_BE(AFMT_U16_LE, AFMT_U16_BE)
|
||||
#endif
|
||||
|
||||
#if !defined(AFMT_U24_NE) && defined(AFMT_U24_LE) && defined(AFMT_U24_BE)
|
||||
#define AFMT_U24_NE MP_SELECT_LE_BE(AFMT_U24_LE, AFMT_U24_BE)
|
||||
#endif
|
||||
|
||||
#if !defined(AFMT_S24_NE) && defined(AFMT_S24_LE) && defined(AFMT_S24_BE)
|
||||
#define AFMT_S24_NE MP_SELECT_LE_BE(AFMT_S24_LE, AFMT_S24_BE)
|
||||
#endif
|
||||
|
||||
#if !defined(AFMT_U32_NE) && defined(AFMT_U32_LE) && defined(AFMT_U32_BE)
|
||||
#define AFMT_U32MP_SELECT_LE_BE(AFMT_U32_LE, AFMT_U32_BE)
|
||||
#endif
|
||||
|
||||
#if !defined(AFMT_S32_NE) && defined(AFMT_S32_LE) && defined(AFMT_S32_BE)
|
||||
#define AFMT_S32MP_SELECT_LE_BE(AFMT_S32_LE, AFMT_S32_BE)
|
||||
#endif
|
||||
|
||||
static const int format_table[][2] = {
|
||||
{AFMT_U8, AF_FORMAT_U8},
|
||||
{AFMT_S8, AF_FORMAT_S8},
|
||||
{AFMT_U16_LE, AF_FORMAT_U16_LE},
|
||||
{AFMT_U16_BE, AF_FORMAT_U16_BE},
|
||||
{AFMT_S16_LE, AF_FORMAT_S16_LE},
|
||||
{AFMT_S16_BE, AF_FORMAT_S16_BE},
|
||||
#ifdef AFMT_S24_PACKED
|
||||
{AFMT_S24_PACKED, AF_FORMAT_S24_LE},
|
||||
{AFMT_U16_NE, AF_FORMAT_U16},
|
||||
{AFMT_S16_NE, AF_FORMAT_S16},
|
||||
#ifdef AFMT_U24_NE
|
||||
{AFMT_U24_NE, AF_FORMAT_U24},
|
||||
#endif
|
||||
#ifdef AFMT_U24_LE
|
||||
{AFMT_U24_LE, AF_FORMAT_U24_LE},
|
||||
#ifdef AFMT_S24_NE
|
||||
{AFMT_S24_NE, AF_FORMAT_S24},
|
||||
#endif
|
||||
#ifdef AFMT_U24_BE
|
||||
{AFMT_U24_BE, AF_FORMAT_U24_BE},
|
||||
#ifdef AFMT_U32_NE
|
||||
{AFMT_U32_NE, AF_FORMAT_U32},
|
||||
#endif
|
||||
#ifdef AFMT_S24_LE
|
||||
{AFMT_S24_LE, AF_FORMAT_S24_LE},
|
||||
#endif
|
||||
#ifdef AFMT_S24_BE
|
||||
{AFMT_S24_BE, AF_FORMAT_S24_BE},
|
||||
#endif
|
||||
#ifdef AFMT_U32_LE
|
||||
{AFMT_U32_LE, AF_FORMAT_U32_LE},
|
||||
#endif
|
||||
#ifdef AFMT_U32_BE
|
||||
{AFMT_U32_BE, AF_FORMAT_U32_BE},
|
||||
#endif
|
||||
#ifdef AFMT_S32_LE
|
||||
{AFMT_S32_LE, AF_FORMAT_S32_LE},
|
||||
#endif
|
||||
#ifdef AFMT_S32_BE
|
||||
{AFMT_S32_BE, AF_FORMAT_S32_BE},
|
||||
#ifdef AFMT_S32_NE
|
||||
{AFMT_S32_NE, AF_FORMAT_S32},
|
||||
#endif
|
||||
#ifdef AFMT_FLOAT
|
||||
{AFMT_FLOAT, AF_FORMAT_FLOAT},
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "ao.h"
|
||||
#include "internal.h"
|
||||
#include "common/msg.h"
|
||||
#include "osdep/endian.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
// for GetFileType to detect pipes
|
||||
|
@ -72,8 +73,7 @@ static void fput32le(uint32_t val, FILE *fp)
|
|||
static void write_wave_header(struct ao *ao, FILE *fp, uint64_t data_length)
|
||||
{
|
||||
bool use_waveex = true;
|
||||
uint16_t fmt = ao->format == AF_FORMAT_FLOAT_LE ?
|
||||
WAV_ID_FLOAT_PCM : WAV_ID_PCM;
|
||||
uint16_t fmt = ao->format == AF_FORMAT_FLOAT ? WAV_ID_FLOAT_PCM : WAV_ID_PCM;
|
||||
uint32_t fmt_chunk_size = use_waveex ? 40 : 16;
|
||||
int bits = af_fmt2bits(ao->format);
|
||||
|
||||
|
@ -124,16 +124,23 @@ static int init(struct ao *ao)
|
|||
if (priv->waveheader) {
|
||||
// WAV files must have one of the following formats
|
||||
|
||||
// And they don't work in big endian; fixing it would be simple, but
|
||||
// nobody cares.
|
||||
if (BYTE_ORDER == BIG_ENDIAN) {
|
||||
MP_FATAL(ao, "Not supported on big endian.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (ao->format) {
|
||||
case AF_FORMAT_U8:
|
||||
case AF_FORMAT_S16_LE:
|
||||
case AF_FORMAT_S24_LE:
|
||||
case AF_FORMAT_S32_LE:
|
||||
case AF_FORMAT_FLOAT_LE:
|
||||
case AF_FORMAT_S16:
|
||||
case AF_FORMAT_S24:
|
||||
case AF_FORMAT_S32:
|
||||
case AF_FORMAT_FLOAT:
|
||||
case AF_FORMAT_AC3:
|
||||
break;
|
||||
default:
|
||||
ao->format = AF_FORMAT_S16_LE;
|
||||
ao->format = AF_FORMAT_S16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,12 +169,9 @@ static const struct format_map {
|
|||
int mp_format;
|
||||
pa_sample_format_t pa_format;
|
||||
} format_maps[] = {
|
||||
{AF_FORMAT_S16_LE, PA_SAMPLE_S16LE},
|
||||
{AF_FORMAT_S16_BE, PA_SAMPLE_S16BE},
|
||||
{AF_FORMAT_S32_LE, PA_SAMPLE_S32LE},
|
||||
{AF_FORMAT_S32_BE, PA_SAMPLE_S32BE},
|
||||
{AF_FORMAT_FLOAT_LE, PA_SAMPLE_FLOAT32LE},
|
||||
{AF_FORMAT_FLOAT_BE, PA_SAMPLE_FLOAT32BE},
|
||||
{AF_FORMAT_S16, PA_SAMPLE_S16NE},
|
||||
{AF_FORMAT_S32, PA_SAMPLE_S32NE},
|
||||
{AF_FORMAT_FLOAT, PA_SAMPLE_FLOAT32NE},
|
||||
{AF_FORMAT_U8, PA_SAMPLE_U8},
|
||||
{AF_FORMAT_UNKNOWN, 0}
|
||||
};
|
||||
|
|
|
@ -52,40 +52,26 @@ static int set_format(struct ao *ao)
|
|||
case AF_FORMAT_S8:
|
||||
rsd_format = RSD_S8;
|
||||
break;
|
||||
case AF_FORMAT_S16_LE:
|
||||
rsd_format = RSD_S16_LE;
|
||||
case AF_FORMAT_S16:
|
||||
rsd_format = RSD_S16_NE;
|
||||
break;
|
||||
case AF_FORMAT_S16_BE:
|
||||
rsd_format = RSD_S16_BE;
|
||||
case AF_FORMAT_U16:
|
||||
rsd_format = RSD_U16_NE;
|
||||
break;
|
||||
case AF_FORMAT_U16_LE:
|
||||
rsd_format = RSD_U16_LE;
|
||||
case AF_FORMAT_S24:
|
||||
case AF_FORMAT_U24:
|
||||
rsd_format = RSD_S32_NE;
|
||||
ao->format = AF_FORMAT_S32;
|
||||
break;
|
||||
case AF_FORMAT_U16_BE:
|
||||
rsd_format = RSD_U16_BE;
|
||||
case AF_FORMAT_S32:
|
||||
rsd_format = RSD_S32_NE;
|
||||
break;
|
||||
case AF_FORMAT_S24_LE:
|
||||
case AF_FORMAT_S24_BE:
|
||||
case AF_FORMAT_U24_LE:
|
||||
case AF_FORMAT_U24_BE:
|
||||
rsd_format = RSD_S32_LE;
|
||||
ao->format = AF_FORMAT_S32_LE;
|
||||
break;
|
||||
case AF_FORMAT_S32_LE:
|
||||
rsd_format = RSD_S32_LE;
|
||||
break;
|
||||
case AF_FORMAT_S32_BE:
|
||||
rsd_format = RSD_S32_BE;
|
||||
break;
|
||||
case AF_FORMAT_U32_LE:
|
||||
rsd_format = RSD_U32_LE;
|
||||
break;
|
||||
case AF_FORMAT_U32_BE:
|
||||
rsd_format = RSD_U32_BE;
|
||||
case AF_FORMAT_U32:
|
||||
rsd_format = RSD_U32_NE;
|
||||
break;
|
||||
default:
|
||||
rsd_format = RSD_S16_LE;
|
||||
ao->format = AF_FORMAT_S16_LE;
|
||||
rsd_format = RSD_S16_NE;
|
||||
ao->format = AF_FORMAT_S16;
|
||||
}
|
||||
|
||||
return rsd_format;
|
||||
|
|
|
@ -38,6 +38,20 @@ struct priv
|
|||
float buflen;
|
||||
};
|
||||
|
||||
static int fmtmap[][2] = {
|
||||
{AF_FORMAT_U8, AUDIO_U8},
|
||||
{AF_FORMAT_S8, AUDIO_S8},
|
||||
{AF_FORMAT_U16, AUDIO_U16SYS},
|
||||
{AF_FORMAT_S16, AUDIO_S16SYS},
|
||||
#ifdef AUDIO_S32SYS
|
||||
{AF_FORMAT_S32, AUDIO_S32SYS},
|
||||
#endif
|
||||
#ifdef AUDIO_F32SYS
|
||||
{AF_FORMAT_FLOAT, AUDIO_F32SYS},
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
|
||||
static void audio_callback(void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
struct ao *ao = userdata;
|
||||
|
@ -104,26 +118,12 @@ static int init(struct ao *ao)
|
|||
|
||||
SDL_AudioSpec desired, obtained;
|
||||
|
||||
switch (ao->format) {
|
||||
case AF_FORMAT_U8: desired.format = AUDIO_U8; break;
|
||||
case AF_FORMAT_S8: desired.format = AUDIO_S8; break;
|
||||
case AF_FORMAT_U16_LE: desired.format = AUDIO_U16LSB; break;
|
||||
case AF_FORMAT_U16_BE: desired.format = AUDIO_U16MSB; break;
|
||||
default:
|
||||
case AF_FORMAT_S16_LE: desired.format = AUDIO_S16LSB; break;
|
||||
case AF_FORMAT_S16_BE: desired.format = AUDIO_S16MSB; break;
|
||||
#ifdef AUDIO_S32LSB
|
||||
case AF_FORMAT_S32_LE: desired.format = AUDIO_S32LSB; break;
|
||||
#endif
|
||||
#ifdef AUDIO_S32MSB
|
||||
case AF_FORMAT_S32_BE: desired.format = AUDIO_S32MSB; break;
|
||||
#endif
|
||||
#ifdef AUDIO_F32LSB
|
||||
case AF_FORMAT_FLOAT_LE: desired.format = AUDIO_F32LSB; break;
|
||||
#endif
|
||||
#ifdef AUDIO_F32MSB
|
||||
case AF_FORMAT_FLOAT_BE: desired.format = AUDIO_F32MSB; break;
|
||||
#endif
|
||||
desired.format = AUDIO_S16SYS;
|
||||
for (int n = 0; fmtmap[n][0]; n++) {
|
||||
if (ao->format == fmtmap[n][0]) {
|
||||
desired.format = fmtmap[n][1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
desired.freq = ao->samplerate;
|
||||
desired.channels = ao->channels.num;
|
||||
|
@ -156,30 +156,18 @@ static int init(struct ao *ao)
|
|||
// large, this will help.
|
||||
ao->device_buffer = 3 * obtained.samples;
|
||||
|
||||
switch (obtained.format) {
|
||||
case AUDIO_U8: ao->format = AF_FORMAT_U8; break;
|
||||
case AUDIO_S8: ao->format = AF_FORMAT_S8; break;
|
||||
case AUDIO_S16LSB: ao->format = AF_FORMAT_S16_LE; break;
|
||||
case AUDIO_S16MSB: ao->format = AF_FORMAT_S16_BE; break;
|
||||
case AUDIO_U16LSB: ao->format = AF_FORMAT_U16_LE; break;
|
||||
case AUDIO_U16MSB: ao->format = AF_FORMAT_U16_BE; break;
|
||||
#ifdef AUDIO_S32LSB
|
||||
case AUDIO_S32LSB: ao->format = AF_FORMAT_S32_LE; break;
|
||||
#endif
|
||||
#ifdef AUDIO_S32MSB
|
||||
case AUDIO_S32MSB: ao->format = AF_FORMAT_S32_BE; break;
|
||||
#endif
|
||||
#ifdef AUDIO_F32LSB
|
||||
case AUDIO_F32LSB: ao->format = AF_FORMAT_FLOAT_LE; break;
|
||||
#endif
|
||||
#ifdef AUDIO_F32MSB
|
||||
case AUDIO_F32MSB: ao->format = AF_FORMAT_FLOAT_BE; break;
|
||||
#endif
|
||||
default:
|
||||
if (!ao->probing)
|
||||
MP_ERR(ao, "could not find matching format\n");
|
||||
uninit(ao);
|
||||
return -1;
|
||||
ao->format = 0;
|
||||
for (int n = 0; fmtmap[n][0]; n++) {
|
||||
if (obtained.format == fmtmap[n][1]) {
|
||||
ao->format = fmtmap[n][0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ao->format) {
|
||||
if (!ao->probing)
|
||||
MP_ERR(ao, "could not find matching format\n");
|
||||
uninit(ao);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ao_chmap_sel_get_def(ao, &sel, &ao->channels, obtained.channels)) {
|
||||
|
|
|
@ -109,22 +109,16 @@ static int init(struct ao *ao)
|
|||
struct priv *p = ao->priv;
|
||||
|
||||
struct af_to_par {
|
||||
int format, bits, sig, le;
|
||||
int format, bits, sig;
|
||||
} static const af_to_par[] = {
|
||||
{AF_FORMAT_U8, 8, 0, 0},
|
||||
{AF_FORMAT_S8, 8, 1, 0},
|
||||
{AF_FORMAT_U16_LE, 16, 0, 1},
|
||||
{AF_FORMAT_U16_BE, 16, 0, 0},
|
||||
{AF_FORMAT_S16_LE, 16, 1, 1},
|
||||
{AF_FORMAT_S16_BE, 16, 1, 0},
|
||||
{AF_FORMAT_U24_LE, 16, 0, 1},
|
||||
{AF_FORMAT_U24_BE, 24, 0, 0},
|
||||
{AF_FORMAT_S24_LE, 24, 1, 1},
|
||||
{AF_FORMAT_S24_BE, 24, 1, 0},
|
||||
{AF_FORMAT_U32_LE, 32, 0, 1},
|
||||
{AF_FORMAT_U32_BE, 32, 0, 0},
|
||||
{AF_FORMAT_S32_LE, 32, 1, 1},
|
||||
{AF_FORMAT_S32_BE, 32, 1, 0}
|
||||
{AF_FORMAT_U8, 8, 0},
|
||||
{AF_FORMAT_S8, 8, 1},
|
||||
{AF_FORMAT_U16, 16, 0},
|
||||
{AF_FORMAT_S16, 16, 1},
|
||||
{AF_FORMAT_U24, 16, 0},
|
||||
{AF_FORMAT_S24, 24, 1},
|
||||
{AF_FORMAT_U32, 32, 0},
|
||||
{AF_FORMAT_S32, 32, 1},
|
||||
}, *ap;
|
||||
int i;
|
||||
|
||||
|
@ -149,7 +143,7 @@ static int init(struct ao *ao)
|
|||
p->par.bits = ap->bits;
|
||||
p->par.sig = ap->sig;
|
||||
if (ap->bits > 8)
|
||||
p->par.le = ap->le;
|
||||
p->par.le = SIO_LE_NATIVE;
|
||||
if (ap->bits != SIO_BPS(ap->bits))
|
||||
p->par.bps = ap->bits / 8;
|
||||
break;
|
||||
|
@ -175,20 +169,18 @@ static int init(struct ao *ao)
|
|||
MP_ERR(ao, "couldn't get params\n");
|
||||
goto error;
|
||||
}
|
||||
if (p->par.bps > 1 && p->par.le != SIO_LE_NATIVE) {
|
||||
MP_ERR(ao, "swapped endian output not supported\n");
|
||||
goto error;
|
||||
}
|
||||
if (p->par.bits == 8 && p->par.bps == 1) {
|
||||
ao->format = p->par.sig ? AF_FORMAT_S8 : AF_FORMAT_U8;
|
||||
} else if (p->par.bits == 16 && p->par.bps == 2) {
|
||||
ao->format = p->par.sig ?
|
||||
(p->par.le ? AF_FORMAT_S16_LE : AF_FORMAT_S16_BE) :
|
||||
(p->par.le ? AF_FORMAT_U16_LE : AF_FORMAT_U16_BE);
|
||||
ao->format = p->par.sig ? AF_FORMAT_S16 : AF_FORMAT_U16;
|
||||
} else if ((p->par.bits == 24 || p->par.msb) && p->par.bps == 3) {
|
||||
ao->format = p->par.sig ?
|
||||
(p->par.le ? AF_FORMAT_S24_LE : AF_FORMAT_S24_BE) :
|
||||
(p->par.le ? AF_FORMAT_U24_LE : AF_FORMAT_U24_BE);
|
||||
ao->format = p->par.sig ? AF_FORMAT_S24 : AF_FORMAT_U24;
|
||||
} else if ((p->par.bits == 32 || p->par.msb) && p->par.bps == 4) {
|
||||
ao->format = p->par.sig ?
|
||||
(p->par.le ? AF_FORMAT_S32_LE : AF_FORMAT_S32_BE) :
|
||||
(p->par.le ? AF_FORMAT_U32_LE : AF_FORMAT_U32_BE);
|
||||
ao->format = p->par.sig ? AF_FORMAT_S32 : AF_FORMAT_U32;
|
||||
} else {
|
||||
MP_ERR(ao, "couldn't set format\n");
|
||||
goto error;
|
||||
|
|
|
@ -292,14 +292,13 @@ static int try_passthrough(struct wasapi_state *state,
|
|||
union WAVEFMT u;
|
||||
u.extensible = &wformat;
|
||||
|
||||
MP_VERBOSE(ao, "trying passthrough for %s...\n",
|
||||
af_fmt_to_str((ao->format&~AF_FORMAT_END_MASK) | AF_FORMAT_LE));
|
||||
MP_VERBOSE(ao, "trying passthrough for %s...\n", af_fmt_to_str(ao->format));
|
||||
|
||||
HRESULT hr = IAudioClient_IsFormatSupported(state->pAudioClient,
|
||||
state->share_mode,
|
||||
u.ex, NULL);
|
||||
if (!FAILED(hr)) {
|
||||
ao->format = (ao->format&~AF_FORMAT_END_MASK) | AF_FORMAT_LE;
|
||||
ao->format = ao->format;
|
||||
state->format = wformat;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -34,10 +34,13 @@
|
|||
#include "video/img_format.h"
|
||||
#include "video/img_fourcc.h"
|
||||
|
||||
#include "osdep/endian.h"
|
||||
|
||||
struct demux_rawaudio_opts {
|
||||
struct mp_chmap channels;
|
||||
int samplerate;
|
||||
int aformat;
|
||||
int endian;
|
||||
};
|
||||
|
||||
#define OPT_BASE_STRUCT struct demux_rawaudio_opts
|
||||
|
@ -46,13 +49,16 @@ const struct m_sub_options demux_rawaudio_conf = {
|
|||
OPT_CHMAP("channels", channels, CONF_MIN, .min = 1),
|
||||
OPT_INTRANGE("rate", samplerate, 0, 1000, 8 * 48000),
|
||||
OPT_AUDIOFORMAT("format", aformat, 0),
|
||||
OPT_CHOICE("endian", endian, 0, ({"native", 0}, {"le", 1}, {"be", 2})),
|
||||
{0}
|
||||
},
|
||||
.size = sizeof(struct demux_rawaudio_opts),
|
||||
.defaults = &(const struct demux_rawaudio_opts){
|
||||
// Note that currently, stream_cdda expects exactly these parameters!
|
||||
.channels = MP_CHMAP_INIT_STEREO,
|
||||
.samplerate = 44100,
|
||||
.aformat = AF_FORMAT_S16,
|
||||
.endian = 0,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -121,6 +127,10 @@ static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check)
|
|||
w->nBlockAlign = w->nChannels * samplesize;
|
||||
w->wBitsPerSample = 8 * samplesize;
|
||||
w->cbSize = 0;
|
||||
int machine_endian = BYTE_ORDER == BIG_ENDIAN ? 2 : 1;
|
||||
int endian = opts->endian ? opts->endian : machine_endian;
|
||||
// wav usually implies little endian
|
||||
sh_audio->big_endian = endian == 2;
|
||||
|
||||
struct priv *p = talloc_ptrtype(demuxer, p);
|
||||
demuxer->priv = p;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "audio/format.h"
|
||||
#include "video/img_fourcc.h"
|
||||
#include "osdep/endian.h"
|
||||
|
||||
#include "stream/stream.h"
|
||||
#include "stream/tv.h"
|
||||
|
@ -106,14 +107,10 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check)
|
|||
{
|
||||
case AF_FORMAT_U8:
|
||||
case AF_FORMAT_S8:
|
||||
case AF_FORMAT_U16_LE:
|
||||
case AF_FORMAT_U16_BE:
|
||||
case AF_FORMAT_S16_LE:
|
||||
case AF_FORMAT_S16_BE:
|
||||
case AF_FORMAT_S32_LE:
|
||||
case AF_FORMAT_S32_BE:
|
||||
case AF_FORMAT_U16:
|
||||
case AF_FORMAT_S16:
|
||||
case AF_FORMAT_S32:
|
||||
break;
|
||||
case AF_FORMAT_MPEG2:
|
||||
default:
|
||||
MP_ERR(tvh, "Audio type '%s' unsupported!\n",
|
||||
af_fmt_to_str(audio_format));
|
||||
|
@ -147,6 +144,8 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check)
|
|||
sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
|
||||
sh_audio->wf->nBlockAlign = block_align;
|
||||
sh_audio->wf->nAvgBytesPerSec = bytes_per_second;
|
||||
// wav header usually implies little endian
|
||||
sh_audio->big_endian = BYTE_ORDER == BIG_ENDIAN;
|
||||
|
||||
MP_VERBOSE(tvh, " TV audio: %d channels, %d bits, %d Hz\n",
|
||||
sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample,
|
||||
|
|
|
@ -70,6 +70,7 @@ typedef struct sh_audio {
|
|||
int bitrate; // compressed bits/sec
|
||||
// win32-compatible codec parameters:
|
||||
MP_WAVEFORMATEX *wf;
|
||||
bool big_endian; // endianess with wf and mp-pcm
|
||||
// note codec extradata may be either under "wf" or "codecdata"
|
||||
unsigned char *codecdata;
|
||||
int codecdata_len;
|
||||
|
|
|
@ -28,4 +28,10 @@
|
|||
|
||||
#endif /* !defined(BYTE_ORDER) */
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define MP_SELECT_LE_BE(LE, BE) BE
|
||||
#else
|
||||
#define MP_SELECT_LE_BE(LE, BE) LE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,7 +51,7 @@ int ai_alsa_setup(audio_in_t *ai)
|
|||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16_LE);
|
||||
err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16);
|
||||
if (err < 0) {
|
||||
MP_ERR(ai, "Sample format not available.\n");
|
||||
return -1;
|
||||
|
@ -122,7 +122,7 @@ int ai_alsa_setup(audio_in_t *ai)
|
|||
snd_pcm_dump(ai->alsa.handle, ai->alsa.log);
|
||||
}
|
||||
|
||||
ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE);
|
||||
ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16);
|
||||
ai->alsa.bits_per_frame = ai->alsa.bits_per_sample * ai->channels;
|
||||
ai->blocksize = ai->alsa.chunk_size * ai->alsa.bits_per_frame / 8;
|
||||
ai->samplesize = ai->alsa.bits_per_sample;
|
||||
|
|
|
@ -100,10 +100,10 @@ int ai_oss_init(audio_in_t *ai)
|
|||
ioctl(ai->oss.audio_fd, SNDCTL_DSP_GETFMTS, &ioctl_param));
|
||||
|
||||
MP_VERBOSE(ai, "Supported formats: %x\n", ioctl_param);
|
||||
if (!(ioctl_param & AFMT_S16_LE))
|
||||
if (!(ioctl_param & AFMT_S16_NE))
|
||||
MP_ERR(ai, "unsupported format\n");
|
||||
|
||||
ioctl_param = AFMT_S16_LE;
|
||||
ioctl_param = AFMT_S16_NE;
|
||||
MP_VERBOSE(ai, "ioctl dsp setfmt: %d\n",
|
||||
err = ioctl(ai->oss.audio_fd, SNDCTL_DSP_SETFMT, &ioctl_param));
|
||||
if (err < 0) {
|
||||
|
|
|
@ -15,7 +15,7 @@ int ai_sndio_setup(audio_in_t *ai)
|
|||
|
||||
par.bits = 16;
|
||||
par.sig = 1;
|
||||
par.le = 1;
|
||||
par.le = SIO_LE_NATIVE;
|
||||
par.rchan = ai->req_channels;
|
||||
par.rate = ai->req_samplerate;
|
||||
par.appbufsz = ai->req_samplerate; /* 1 sec */
|
||||
|
|
|
@ -922,7 +922,7 @@ static int do_control(priv_t *priv, int cmd, void *arg)
|
|||
case TVI_CONTROL_AUD_GET_FORMAT:
|
||||
init_audio(priv);
|
||||
if (!priv->audio_initialized) return TVI_CONTROL_FALSE;
|
||||
*(int *)arg = AF_FORMAT_S16_LE;
|
||||
*(int *)arg = AF_FORMAT_S16;
|
||||
MP_VERBOSE(priv, "%s: get audio format: %d\n",
|
||||
info.short_name, *(int *)arg);
|
||||
return TVI_CONTROL_TRUE;
|
||||
|
|
Loading…
Reference in New Issue