mirror of https://github.com/mpv-player/mpv
audio/out: channel map selection
Make all AOs use what has been introduced in the previous commit. Note that even AOs which can handle all possible layouts (like ao_null) use the new functions. This might be important if in the future ao_select_champ() possibly honors global user options about downmixing and so on.
This commit is contained in:
parent
ab8f28a672
commit
ecc6e379b2
|
@ -129,6 +129,4 @@ void mp_chmap_print_help(int msgt, int msgl);
|
|||
#define mp_chmap_is_waveext mp_chmap_is_lavc
|
||||
#define mp_chmap_reorder_to_waveext mp_chmap_reorder_to_lavc
|
||||
|
||||
#define mp_chmap_reorder_to_alsa(x) mp_chmap_from_channels_alsa((x), (x)->num)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -330,22 +330,35 @@ static const char *device_channel_layouts[][2] = {
|
|||
{"surround41", "fl-fr-bl-br-lfe"},
|
||||
{"surround51", "fl-fr-bl-br-fc-lfe"},
|
||||
{"surround71", "fl-fr-bl-br-fc-lfe-sl-sr"},
|
||||
{0}
|
||||
};
|
||||
|
||||
// Find a device that contains exactly all the requested speakers.
|
||||
// Set *request to the required channel order.
|
||||
static const char *find_device(struct mp_chmap *request)
|
||||
#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define NUM_ALSA_CHMAPS ARRAY_LEN(device_channel_layouts)
|
||||
|
||||
static const char *select_chmap(struct ao *ao)
|
||||
{
|
||||
for (int n = 0; device_channel_layouts[n][0]; n++) {
|
||||
struct mp_chmap map = {0};
|
||||
mp_chmap_from_str(&map, bstr0(device_channel_layouts[n][1]));
|
||||
if (mp_chmap_equals_reordered(&map, request)) {
|
||||
*request = map;
|
||||
struct mp_chmap_sel sel = {0};
|
||||
struct mp_chmap maps[NUM_ALSA_CHMAPS];
|
||||
for (int n = 0; n < NUM_ALSA_CHMAPS; n++) {
|
||||
mp_chmap_from_str(&maps[n], bstr0(device_channel_layouts[n][1]));
|
||||
mp_chmap_sel_add_map(&sel, &maps[n]);
|
||||
};
|
||||
|
||||
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
|
||||
return NULL;
|
||||
|
||||
for (int n = 0; n < NUM_ALSA_CHMAPS; n++) {
|
||||
if (mp_chmap_equals(&ao->channels, &maps[n]))
|
||||
return device_channel_layouts[n][0];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
char *name = mp_chmap_to_str(&ao->channels);
|
||||
mp_tmsg(MSGT_AO, MSGL_ERR,
|
||||
"[AO_ALSA] channel layout %s (%d ch) not supported.\n",
|
||||
name, ao->channels.num);
|
||||
talloc_free(name);
|
||||
return "default";
|
||||
}
|
||||
|
||||
static int try_open_device(struct ao *ao, const char *device, int open_mode,
|
||||
|
@ -449,16 +462,7 @@ static int init(struct ao *ao, char *params)
|
|||
"alsa-spdif-init: playing AC3/iec61937/iec958, %i channels\n",
|
||||
ao->channels.num);
|
||||
} else {
|
||||
device.str = find_device(&ao->channels);
|
||||
if (!device.str) {
|
||||
char *name = mp_chmap_to_str(&ao->channels);
|
||||
device.str = "default";
|
||||
mp_chmap_from_channels(&ao->channels, ao->channels.num);
|
||||
mp_tmsg(MSGT_AO, MSGL_ERR,
|
||||
"[AO_ALSA] channel layout %s (%d ch) not supported.\n",
|
||||
name, ao->channels.num);
|
||||
talloc_free(name);
|
||||
}
|
||||
device.str = select_chmap(ao);
|
||||
if (strcmp(device.str, "default") != 0 && ao->format == AF_FORMAT_FLOAT_NE)
|
||||
{
|
||||
// hack - use the converter plugin (why the heck?)
|
||||
|
@ -535,8 +539,11 @@ static int init(struct ao *ao, char *params)
|
|||
(p->alsa, alsa_hwparams, &num_channels);
|
||||
CHECK_ALSA_ERROR("Unable to set channels");
|
||||
|
||||
if (num_channels != ao->channels.num)
|
||||
mp_chmap_from_channels(&ao->channels, num_channels);
|
||||
if (num_channels != ao->channels.num) {
|
||||
mp_tmsg(MSGT_AO, MSGL_ERR,
|
||||
"[AO_ALSA] Couldn't get requested number of channels.\n");
|
||||
mp_chmap_from_channels_alsa(&ao->channels, num_channels);
|
||||
}
|
||||
|
||||
/* workaround for buggy rate plugin (should be fixed in ALSA 1.0.11)
|
||||
prefer our own resampler, since that allows users to choose the resampler,
|
||||
|
|
|
@ -499,6 +499,11 @@ int device_id, display_help = 0;
|
|||
// Save selected device id
|
||||
ao->i_selected_dev = devid_def;
|
||||
|
||||
struct mp_chmap_sel chmap_sel = {0};
|
||||
mp_chmap_sel_add_waveext(&chmap_sel);
|
||||
if (!ao_chmap_sel_adjust(&ao_data, &ao_data.channels, &chmap_sel))
|
||||
goto err_out;
|
||||
|
||||
// Build Description for the input format
|
||||
inDesc.mSampleRate=rate;
|
||||
inDesc.mFormatID=ao->b_supports_digital ? kAudioFormat60958AC3 : kAudioFormatLinearPCM;
|
||||
|
@ -605,8 +610,8 @@ int device_id, display_help = 0;
|
|||
ao->chunk_size = maxFrames;//*inDesc.mBytesPerFrame;
|
||||
|
||||
ao_data.samplerate = inDesc.mSampleRate;
|
||||
mp_chmap_from_channels(&ao_data.channels, inDesc.mChannelsPerFrame);
|
||||
mp_chmap_reorder_to_waveext(&ao_data.channels);
|
||||
if (!ao_chmap_sel_get_def(&ao_data, &chmap_sel, &ao_data.channels, inDesc.mChannelsPerFrame))
|
||||
goto err_out2;
|
||||
ao_data.bps = ao_data.samplerate * inDesc.mBytesPerFrame;
|
||||
ao_data.outburst = ao->chunk_size;
|
||||
ao_data.buffersize = ao_data.bps;
|
||||
|
@ -838,7 +843,7 @@ static int OpenSPDIF(void)
|
|||
ao->chunk_size = ao->stream_format.mBytesPerPacket;
|
||||
|
||||
ao_data.samplerate = ao->stream_format.mSampleRate;
|
||||
// Applies default ordering; ok becazse AC3 data is always in mpv internal channel order
|
||||
// Applies default ordering; ok because AC3 data is always in mpv internal channel order
|
||||
mp_chmap_from_channels(&ao_data.channels, ao->stream_format.mChannelsPerFrame);
|
||||
ao_data.bps = ao_data.samplerate * (ao->stream_format.mBytesPerPacket/ao->stream_format.mFramesPerPacket);
|
||||
ao_data.outburst = ao->chunk_size;
|
||||
|
|
|
@ -390,18 +390,14 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
|
|||
DSBUFFERDESC dsbpridesc;
|
||||
DSBUFFERDESC dsbdesc;
|
||||
|
||||
//check if the channel count and format is supported in general
|
||||
if (ao_data.channels.num > 8) {
|
||||
// More than 8 channels might just work, but needs testing
|
||||
UninitDirectSound();
|
||||
mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: > 8 channel audio not yet supported\n");
|
||||
if (AF_FORMAT_IS_AC3(format)) {
|
||||
format = AF_FORMAT_AC3_NE;
|
||||
} else {
|
||||
struct mp_chmap_sel sel = {0};
|
||||
mp_chmap_sel_add_waveext(&sel);
|
||||
if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (AF_FORMAT_IS_AC3(format))
|
||||
format = AF_FORMAT_AC3_NE;
|
||||
else
|
||||
mp_chmap_reorder_to_waveext(&ao_data.channels);
|
||||
switch(format){
|
||||
case AF_FORMAT_AC3_NE:
|
||||
case AF_FORMAT_S24_LE:
|
||||
|
|
|
@ -50,7 +50,7 @@ static const ao_info_t info =
|
|||
LIBAO_EXTERN(jack)
|
||||
|
||||
//! maximum number of channels supported, avoids lots of mallocs
|
||||
#define MAX_CHANS 8
|
||||
#define MAX_CHANS MP_NUM_CHANNELS
|
||||
static jack_port_t *ports[MAX_CHANS];
|
||||
static int num_ports; ///< Number of used ports == number of channels
|
||||
static jack_client_t *client;
|
||||
|
@ -223,11 +223,12 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
|
|||
print_help();
|
||||
return 0;
|
||||
}
|
||||
if (ao_data.channels.num > MAX_CHANS) {
|
||||
mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] Invalid number of channels: %i\n",
|
||||
ao_data.channels.num);
|
||||
|
||||
struct mp_chmap_sel sel = {0};
|
||||
mp_chmap_sel_add_waveext(&sel);
|
||||
if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (!client_name) {
|
||||
client_name = malloc(40);
|
||||
sprintf(client_name, "mpv [%d]", getpid());
|
||||
|
@ -283,8 +284,9 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
|
|||
/ (float)rate;
|
||||
callback_interval = 0;
|
||||
|
||||
mp_chmap_from_channels(&ao_data.channels, num_ports);
|
||||
mp_chmap_reorder_to_alsa(&ao_data.channels); // what order does hack use?
|
||||
if (!ao_chmap_sel_get_def(&ao_data, &sel, &ao_data.channels, num_ports))
|
||||
goto err_out;
|
||||
|
||||
ao_data.samplerate = rate;
|
||||
ao_data.format = AF_FORMAT_FLOAT_NE;
|
||||
ao_data.bps = ao_data.channels.num * rate * sizeof(float);
|
||||
|
|
|
@ -102,6 +102,10 @@ static int init(struct ao *ao, char *params)
|
|||
|
||||
ac->stream->codec->sample_rate = ao->samplerate;
|
||||
|
||||
struct mp_chmap_sel sel = {0};
|
||||
mp_chmap_sel_add_any(&sel);
|
||||
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
|
||||
return -1;
|
||||
mp_chmap_reorder_to_lavc(&ao->channels);
|
||||
ac->stream->codec->channels = ao->channels.num;
|
||||
ac->stream->codec->channel_layout = mp_chmap_to_lavc(&ao->channels);
|
||||
|
|
|
@ -48,6 +48,12 @@ static int init(struct ao *ao, char *params)
|
|||
{
|
||||
struct priv *priv = talloc_zero(ao, struct priv);
|
||||
ao->priv = priv;
|
||||
|
||||
struct mp_chmap_sel sel = {0};
|
||||
mp_chmap_sel_add_any(&sel);
|
||||
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
|
||||
return -1;
|
||||
|
||||
int samplesize = af_fmt2bits(ao->format) / 8;
|
||||
ao->outburst = 256 * ao->channels.num * samplesize;
|
||||
// A "buffer" for about 0.2 seconds of audio
|
||||
|
|
|
@ -53,7 +53,7 @@ static const ao_info_t info =
|
|||
|
||||
LIBAO_EXTERN(openal)
|
||||
|
||||
#define MAX_CHANS 8
|
||||
#define MAX_CHANS MP_NUM_CHANNELS
|
||||
#define NUM_BUF 128
|
||||
#define CHUNK_SIZE 512
|
||||
static ALuint buffers[MAX_CHANS][NUM_BUF];
|
||||
|
@ -151,11 +151,11 @@ static int init(int rate, const struct mp_chmap *channels, int format,
|
|||
list_devices();
|
||||
goto err_out;
|
||||
}
|
||||
if (ao_data.channels.num > MAX_CHANS) {
|
||||
mp_msg(MSGT_AO, MSGL_FATAL, "[OpenAL] Invalid number of channels: %i\n",
|
||||
ao_data.channels.num);
|
||||
struct mp_chmap_sel sel = {0};
|
||||
for (i = 0; speaker_pos[i].id != -1; i++)
|
||||
mp_chmap_sel_add_speaker(&sel, speaker_pos[i].id);
|
||||
if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
|
||||
goto err_out;
|
||||
}
|
||||
struct speaker speakers[MAX_CHANS];
|
||||
for (i = 0; i < ao_data.channels.num; i++) {
|
||||
speakers[i].id = -1;
|
||||
|
|
|
@ -340,7 +340,10 @@ ac3_retry:
|
|||
af_fmt2str_short(ao_data.format), af_fmt2str_short(format));
|
||||
|
||||
if(!AF_FORMAT_IS_AC3(format)) {
|
||||
mp_chmap_reorder_to_alsa(&ao_data.channels);
|
||||
struct mp_chmap_sel sel = {0};
|
||||
mp_chmap_sel_add_alsa_def(&sel);
|
||||
if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
|
||||
return 0;
|
||||
int reqchannels = ao_data.channels.num;
|
||||
// We only use SNDCTL_DSP_CHANNELS for >2 channels, in case some drivers don't have it
|
||||
if (reqchannels > 2) {
|
||||
|
@ -357,7 +360,8 @@ ac3_retry:
|
|||
mp_tmsg(MSGT_AO,MSGL_ERR,"[AO OSS] audio_setup: Failed to set audio device to %d channels.\n", reqchannels);
|
||||
return 0;
|
||||
}
|
||||
mp_chmap_from_channels(&ao_data.channels, c + 1);
|
||||
if (!ao_chmap_sel_get_def(&ao_data, &sel, &ao_data.channels, c + 1))
|
||||
return 0;
|
||||
}
|
||||
mp_msg(MSGT_AO,MSGL_V,"audio_setup: using %d channels (requested: %d)\n", ao_data.channels.num, reqchannels);
|
||||
// set rate
|
||||
|
|
|
@ -146,7 +146,10 @@ static int init(struct ao *ao, char *params)
|
|||
}
|
||||
}
|
||||
|
||||
mp_chmap_reorder_to_waveext(&ao->channels);
|
||||
struct mp_chmap_sel sel = {0};
|
||||
mp_chmap_sel_add_waveext(&sel);
|
||||
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
|
||||
return -1;
|
||||
|
||||
ao->outburst = 65536;
|
||||
ao->bps = ao->channels.num * ao->samplerate * (af_fmt2bits(ao->format) / 8);
|
||||
|
|
|
@ -273,7 +273,11 @@ static int init(struct ao *ao, char *params)
|
|||
if (pa_device == paNoDevice)
|
||||
goto error_exit;
|
||||
|
||||
mp_chmap_reorder_to_alsa(&ao->channels);
|
||||
// The actual channel order probably depends on the platform.
|
||||
struct mp_chmap_sel sel = {0};
|
||||
mp_chmap_sel_add_waveext_def(&sel);
|
||||
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
|
||||
goto error_exit;
|
||||
|
||||
PaStreamParameters sp = {
|
||||
.device = pa_device,
|
||||
|
|
|
@ -187,6 +187,15 @@ static bool chmap_pa_from_mp(pa_channel_map *dst, struct mp_chmap *src)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool select_chmap(struct ao *ao, pa_channel_map *dst)
|
||||
{
|
||||
struct mp_chmap_sel sel = {0};
|
||||
for (int n = 0; speaker_map[n][1] != -1; n++)
|
||||
mp_chmap_sel_add_speaker(&sel, speaker_map[n][1]);
|
||||
return ao_chmap_sel_adjust(ao, &sel, &ao->channels) &&
|
||||
chmap_pa_from_mp(dst, &ao->channels);
|
||||
}
|
||||
|
||||
static void uninit(struct ao *ao, bool cut_audio)
|
||||
{
|
||||
struct priv *priv = ao->priv;
|
||||
|
@ -301,16 +310,8 @@ static int init(struct ao *ao, char *params)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!chmap_pa_from_mp(&map, &ao->channels)) {
|
||||
char *name = mp_chmap_to_str(&ao->channels);
|
||||
mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Can't map %s channel layout\n",
|
||||
name);
|
||||
talloc_free(name);
|
||||
// Not a really good fallback, since this doesn't trigger if the
|
||||
// channel map is valid, but unsupported by the output device.
|
||||
ao->channels = (struct mp_chmap) MP_CHMAP_INIT_STEREO;
|
||||
pa_channel_map_init_stereo(&map);
|
||||
}
|
||||
if (!select_chmap(ao, &map))
|
||||
goto fail;
|
||||
|
||||
ao->bps = pa_bytes_per_second(&ss);
|
||||
|
||||
|
|
|
@ -121,7 +121,13 @@ static int init(struct ao *ao, char *params)
|
|||
free(port);
|
||||
}
|
||||
|
||||
mp_chmap_reorder_to_alsa(&ao->channels);
|
||||
// Actual channel layout unknown.
|
||||
struct mp_chmap_sel sel = {0};
|
||||
mp_chmap_sel_add_waveext_def(&sel);
|
||||
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) {
|
||||
rsd_free(priv->rd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rsd_set_param(priv->rd, RSD_SAMPLERATE, &ao->samplerate);
|
||||
rsd_set_param(priv->rd, RSD_CHANNELS, &ao->channels.num);
|
||||
|
|
|
@ -160,6 +160,13 @@ static int init(struct ao *ao, char *params)
|
|||
return -1;
|
||||
}
|
||||
|
||||
struct mp_chmap_sel sel = {0};
|
||||
mp_chmap_sel_add_waveext_def(&sel);
|
||||
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) {
|
||||
uninit(ao, true);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_AudioSpec desired, obtained;
|
||||
|
||||
int bytes = 0;
|
||||
|
@ -236,9 +243,12 @@ static int init(struct ao *ao, char *params)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!ao_chmap_sel_get_def(ao, &sel, &ao->channels, obtained.channels)) {
|
||||
uninit(ao, true);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ao->samplerate = obtained.freq;
|
||||
mp_chmap_from_channels(&ao->channels, obtained.channels);
|
||||
mp_chmap_reorder_to_alsa(&ao->channels);
|
||||
ao->bps = ao->channels.num * ao->samplerate * bytes;
|
||||
ao->buffersize = obtained.size * bufcnt;
|
||||
ao->outburst = obtained.size;
|
||||
|
|
Loading…
Reference in New Issue