aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--audio/decode/dec_audio.c7
-rw-r--r--audio/decode/dec_audio.h4
-rw-r--r--audio/mixer.c2
-rw-r--r--audio/out/ao.c2
-rw-r--r--audio/out/ao.h5
-rw-r--r--audio/out/ao_alsa.c31
-rw-r--r--audio/out/ao_coreaudio.c15
-rw-r--r--audio/out/ao_dsound.c83
-rw-r--r--audio/out/ao_jack.c17
-rw-r--r--audio/out/ao_lavc.c86
-rw-r--r--audio/out/ao_null.c4
-rw-r--r--audio/out/ao_openal.c43
-rw-r--r--audio/out/ao_oss.c32
-rw-r--r--audio/out/ao_pcm.c34
-rw-r--r--audio/out/ao_portaudio.c6
-rw-r--r--audio/out/ao_pulse.c6
-rw-r--r--audio/out/ao_rsound.c6
-rw-r--r--audio/out/ao_sdl.c7
-rw-r--r--audio/out/audio_out_internal.h3
-rw-r--r--core/mplayer.c8
20 files changed, 162 insertions, 239 deletions
diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c
index 6c8804eec9..11232f9271 100644
--- a/audio/decode/dec_audio.c
+++ b/audio/decode/dec_audio.c
@@ -199,7 +199,8 @@ void uninit_audio(sh_audio_t *sh_audio)
int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate,
- int *out_samplerate, int *out_channels, int *out_format)
+ int *out_samplerate, struct mp_chmap *out_channels,
+ int *out_format)
{
struct af_stream *afs = sh_audio->afilter;
if (!afs)
@@ -211,7 +212,7 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate,
// output format: same as ao driver's input format (if missing, fallback to input)
afs->output.rate = *out_samplerate;
- mp_audio_set_num_channels(&afs->output, *out_channels);
+ mp_audio_set_channels(&afs->output, out_channels);
mp_audio_set_format(&afs->output, *out_format);
// filter config:
@@ -231,7 +232,7 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate,
}
*out_samplerate = afs->output.rate;
- *out_channels = afs->output.nch;
+ *out_channels = afs->output.channels;
*out_format = afs->output.format;
// ok!
diff --git a/audio/decode/dec_audio.h b/audio/decode/dec_audio.h
index 9fa6aad8dd..b46f4282fb 100644
--- a/audio/decode/dec_audio.h
+++ b/audio/decode/dec_audio.h
@@ -19,6 +19,7 @@
#ifndef MPLAYER_DEC_AUDIO_H
#define MPLAYER_DEC_AUDIO_H
+#include "audio/chmap.h"
#include "demux/stheader.h"
struct bstr;
@@ -33,6 +34,7 @@ void skip_audio_frame(sh_audio_t *sh_audio);
void uninit_audio(sh_audio_t *sh_audio);
int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate,
- int *out_samplerate, int *out_channels, int *out_format);
+ int *out_samplerate, struct mp_chmap *out_channels,
+ int *out_format);
#endif /* MPLAYER_DEC_AUDIO_H */
diff --git a/audio/mixer.c b/audio/mixer.c
index b67e548a3c..0f1a7871d6 100644
--- a/audio/mixer.c
+++ b/audio/mixer.c
@@ -217,7 +217,7 @@ void mixer_setbalance(mixer_t *mixer, float val)
AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val))
return;
- if (val == 0 || mixer->ao->channels < 2)
+ if (val == 0 || mixer->ao->channels.num < 2)
return;
if (!(af_pan_balance = af_add(mixer->afilter, "pan"))) {
diff --git a/audio/out/ao.c b/audio/out/ao.c
index 9fb201a333..bf9b47a14e 100644
--- a/audio/out/ao.c
+++ b/audio/out/ao.c
@@ -257,7 +257,7 @@ int old_ao_init(struct ao *ao, char *params)
assert(!global_ao);
global_ao = ao;
ao_subdevice = params ? talloc_strdup(ao, params) : NULL;
- if (ao->driver->old_functions->init(ao->samplerate, ao->channels,
+ if (ao->driver->old_functions->init(ao->samplerate, &ao->channels,
ao->format, 0) == 0) {
global_ao = NULL;
return -1;
diff --git a/audio/out/ao.h b/audio/out/ao.h
index e57fff7a95..465bcf6197 100644
--- a/audio/out/ao.h
+++ b/audio/out/ao.h
@@ -23,6 +23,7 @@
#include "core/bstr.h"
#include "core/mp_common.h"
+#include "audio/chmap.h"
enum aocontrol {
// _VOLUME commands take struct ao_control_vol pointer for input/output.
@@ -55,7 +56,7 @@ typedef struct ao_info {
/* interface towards mplayer and */
typedef struct ao_old_functions {
int (*control)(int cmd, void *arg);
- int (*init)(int rate, int channels, int format, int flags);
+ int (*init)(int rate, const struct mp_chmap *channels, int format, int flags);
void (*uninit)(int immed);
void (*reset)(void);
int (*get_space)(void);
@@ -86,7 +87,7 @@ struct ao_driver {
/* global data used by mplayer and plugins */
struct ao {
int samplerate;
- int channels;
+ struct mp_chmap channels;
int format;
int bps; // bytes per second
int outburst;
diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c
index 3682e76aa3..a194ce0478 100644
--- a/audio/out/ao_alsa.c
+++ b/audio/out/ao_alsa.c
@@ -332,7 +332,8 @@ static int try_open_device(const char *device, int open_mode, int try_ac3)
open & setup audio device
return: 1=success 0=fail
*/
-static int init(int rate_hz, int channels, int format, int flags)
+static int init(int rate_hz, const struct mp_chmap *channels, int format,
+ int flags)
{
int err;
int block;
@@ -351,7 +352,7 @@ static int init(int rate_hz, int channels, int format, int flags)
memset(alsa_device, 0, ALSA_DEVICE_SIZE + 1);
mp_msg(MSGT_AO,MSGL_V,"alsa-init: requested format: %d Hz, %d channels, %x\n", rate_hz,
- channels, format);
+ ao_data.channels.num, format);
alsa_handler = NULL;
mp_msg(MSGT_AO,MSGL_V,"alsa-init: using ALSA %s\n", snd_asoundlib_version());
@@ -360,10 +361,6 @@ static int init(int rate_hz, int channels, int format, int flags)
snd_lib_error_set_handler(alsa_error_handler);
- ao_data.samplerate = rate_hz;
- ao_data.format = format;
- ao_data.channels = channels;
-
switch (format)
{
case AF_FORMAT_S8:
@@ -435,13 +432,13 @@ static int init(int rate_hz, int channels, int format, int flags)
*/
if (AF_FORMAT_IS_IEC61937(format)) {
device.str = "iec958";
- mp_msg(MSGT_AO,MSGL_V,"alsa-spdif-init: playing AC3/iec61937/iec958, %i channels\n", channels);
+ mp_msg(MSGT_AO,MSGL_V,"alsa-spdif-init: playing AC3/iec61937/iec958, %i channels\n", ao_data.channels.num);
}
else
/* in any case for multichannel playback we should select
* appropriate device
*/
- switch (channels) {
+ switch (ao_data.channels.num) {
case 1:
case 2:
device.str = "default";
@@ -471,7 +468,8 @@ static int init(int rate_hz, int channels, int format, int flags)
break;
default:
device.str = "default";
- mp_tmsg(MSGT_AO,MSGL_ERR,"[AO_ALSA] %d channels are not supported.\n",channels);
+ mp_tmsg(MSGT_AO,MSGL_ERR,"[AO_ALSA] %d channels are not supported.\n",
+ ao_data.channels.num);
}
device.len = strlen(device.str);
if (subopt_parse(ao_subdevice, subopts) != 0) {
@@ -554,13 +552,17 @@ static int init(int rate_hz, int channels, int format, int flags)
return 0;
}
+ int num_channels = ao_data.channels.num;
if ((err = snd_pcm_hw_params_set_channels_near(alsa_handler, alsa_hwparams,
- &ao_data.channels)) < 0)
+ &num_channels)) < 0)
{
mp_tmsg(MSGT_AO,MSGL_ERR,"[AO_ALSA] Unable to set channels: %s\n",
snd_strerror(err));
return 0;
}
+ mp_chmap_from_channels(&ao_data.channels, num_channels);
+ if (!AF_FORMAT_IS_IEC61937(format))
+ mp_chmap_reorder_to_alsa(&ao_data.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,
@@ -582,7 +584,7 @@ static int init(int rate_hz, int channels, int format, int flags)
}
bytes_per_sample = af_fmt2bits(ao_data.format) / 8;
- bytes_per_sample *= ao_data.channels;
+ bytes_per_sample *= ao_data.channels.num;
ao_data.bps = ao_data.samplerate * bytes_per_sample;
if ((err = snd_pcm_hw_params_set_buffer_time_near(alsa_handler, alsa_hwparams,
@@ -668,7 +670,7 @@ static int init(int rate_hz, int channels, int format, int flags)
alsa_can_pause = snd_pcm_hw_params_can_pause(alsa_hwparams);
mp_msg(MSGT_AO,MSGL_V,"alsa: %d Hz/%d channels/%d bpf/%d bytes buffer/%s\n",
- ao_data.samplerate, ao_data.channels, (int)bytes_per_sample, ao_data.buffersize,
+ ao_data.samplerate, ao_data.channels.num, (int)bytes_per_sample, ao_data.buffersize,
snd_pcm_format_description(alsa_format));
} // end switch alsa_handler (spdif)
@@ -791,11 +793,6 @@ static int play(void* data, int len, int flags)
len = len / ao_data.outburst * ao_data.outburst;
num_frames = len / bytes_per_sample;
- int bps = af_fmt2bits(ao_data.format) / 8;
- reorder_channel_nch(data, AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
- AF_CHANNEL_LAYOUT_ALSA_DEFAULT,
- ao_data.channels, len / bps, bps);
-
//mp_msg(MSGT_AO,MSGL_ERR,"alsa-play: frames=%i, len=%i\n",num_frames,len);
if (!alsa_handler) {
diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c
index 7993eac910..98b9f9adeb 100644
--- a/audio/out/ao_coreaudio.c
+++ b/audio/out/ao_coreaudio.c
@@ -412,7 +412,7 @@ static void print_help(void)
free(devids);
}
-static int init(int rate,int channels,int format,int flags)
+static int init(int rate,const struct mp_chmap *channels,int format,int flags)
{
AudioStreamBasicDescription inDesc;
AudioComponentDescription desc;
@@ -439,7 +439,7 @@ int device_id, display_help = 0;
return 0;
}
- ao_msg(MSGT_AO,MSGL_V, "init([%dHz][%dch][%s][%d])\n", rate, channels, af_fmt2str_short(format), flags);
+ ao_msg(MSGT_AO,MSGL_V, "init([%dHz][%dch][%s][%d])\n", rate, ao_data.channels.num, af_fmt2str_short(format), flags);
ao = calloc(1, sizeof(ao_coreaudio_t));
@@ -502,7 +502,7 @@ int device_id, display_help = 0;
// Build Description for the input format
inDesc.mSampleRate=rate;
inDesc.mFormatID=ao->b_supports_digital ? kAudioFormat60958AC3 : kAudioFormatLinearPCM;
- inDesc.mChannelsPerFrame=channels;
+ inDesc.mChannelsPerFrame=ao_data.channels.num;
inDesc.mBitsPerChannel=af_fmt2bits(format);
if((format&AF_FORMAT_POINT_MASK)==AF_FORMAT_F) {
@@ -521,7 +521,7 @@ int device_id, display_help = 0;
inDesc.mFormatFlags |= kAudioFormatFlagIsBigEndian;
inDesc.mFramesPerPacket = 1;
- ao->packetSize = inDesc.mBytesPerPacket = inDesc.mBytesPerFrame = inDesc.mFramesPerPacket*channels*(inDesc.mBitsPerChannel/8);
+ ao->packetSize = inDesc.mBytesPerPacket = inDesc.mBytesPerFrame = inDesc.mFramesPerPacket*ao_data.channels.num*(inDesc.mBitsPerChannel/8);
print_format(MSGL_V, "source:",&inDesc);
if (ao->b_supports_digital)
@@ -605,7 +605,9 @@ int device_id, display_help = 0;
ao->chunk_size = maxFrames;//*inDesc.mBytesPerFrame;
ao_data.samplerate = inDesc.mSampleRate;
- ao_data.channels = inDesc.mChannelsPerFrame;
+ mp_chmap_from_channels(&ao_data.channels, inDesc.mChannelsPerFrame);
+ // Most likely wrong, but that's what it has been set to.
+ mp_chmap_reorder_to_alsa(&ao_data.channels);
ao_data.bps = ao_data.samplerate * inDesc.mBytesPerFrame;
ao_data.outburst = ao->chunk_size;
ao_data.buffersize = ao_data.bps;
@@ -837,7 +839,8 @@ static int OpenSPDIF(void)
ao->chunk_size = ao->stream_format.mBytesPerPacket;
ao_data.samplerate = ao->stream_format.mSampleRate;
- ao_data.channels = ao->stream_format.mChannelsPerFrame;
+ // Applies default ordering; ok becazse 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;
ao_data.buffersize = ao_data.bps;
diff --git a/audio/out/ao_dsound.c b/audio/out/ao_dsound.c
index 9ad27306bd..b096dd28db 100644
--- a/audio/out/ao_dsound.c
+++ b/audio/out/ao_dsound.c
@@ -64,26 +64,6 @@ LIBAO_EXTERN(dsound)
static const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x1,0x0000,0x0010, {0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}};
-#define SPEAKER_FRONT_LEFT 0x1
-#define SPEAKER_FRONT_RIGHT 0x2
-#define SPEAKER_FRONT_CENTER 0x4
-#define SPEAKER_LOW_FREQUENCY 0x8
-#define SPEAKER_BACK_LEFT 0x10
-#define SPEAKER_BACK_RIGHT 0x20
-#define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
-#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
-#define SPEAKER_BACK_CENTER 0x100
-#define SPEAKER_SIDE_LEFT 0x200
-#define SPEAKER_SIDE_RIGHT 0x400
-#define SPEAKER_TOP_CENTER 0x800
-#define SPEAKER_TOP_FRONT_LEFT 0x1000
-#define SPEAKER_TOP_FRONT_CENTER 0x2000
-#define SPEAKER_TOP_FRONT_RIGHT 0x4000
-#define SPEAKER_TOP_BACK_LEFT 0x8000
-#define SPEAKER_TOP_BACK_CENTER 0x10000
-#define SPEAKER_TOP_BACK_RIGHT 0x20000
-#define SPEAKER_RESERVED 0x80000000
-
#if 0
#define DSSPEAKER_HEADPHONE 0x00000001
#define DSSPEAKER_MONO 0x00000002
@@ -107,28 +87,6 @@ typedef struct {
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
#endif
-static const int channel_mask[] = {
- /* 1 */ SPEAKER_FRONT_CENTER,
- /* 2 */ SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT,
- /* 3 */ SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT
- | SPEAKER_LOW_FREQUENCY,
- /* 4 */ SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT
- | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
- /* 5 */ SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT
- | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
- | SPEAKER_LOW_FREQUENCY,
- /* 6 */ SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT
- | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
- | SPEAKER_LOW_FREQUENCY,
- /* 7 */ SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT
- | SPEAKER_BACK_LEFT | SPEAKER_BACK_CENTER | SPEAKER_BACK_RIGHT
- | SPEAKER_LOW_FREQUENCY,
- /* 8 */ SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT
- | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
- | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT
- | SPEAKER_LOW_FREQUENCY,
-};
-
static HINSTANCE hdsound_dll = NULL; ///handle to the dll
static LPDIRECTSOUND hds = NULL; ///direct sound object
static LPDIRECTSOUNDBUFFER hdspribuf = NULL; ///primary direct sound buffer
@@ -349,22 +307,9 @@ static int write_buffer(unsigned char *data, int len)
if (SUCCEEDED(res))
{
if (!AF_FORMAT_IS_AC3(ao_data.format)) {
- int sampsize = af_fmt2bits(ao_data.format) / 8;
- reorder_channel_copy_nch(data,
- AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
- lpvPtr1,
- AF_CHANNEL_LAYOUT_WAVEEX_DEFAULT,
- ao_data.channels,
- dwBytes1 / sampsize,
- sampsize);
+ memcpy(lpvPtr1, data, dwBytes1);
if (lpvPtr2 != NULL)
- reorder_channel_copy_nch(data + dwBytes1,
- AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
- lpvPtr2,
- AF_CHANNEL_LAYOUT_WAVEEX_DEFAULT,
- ao_data.channels,
- dwBytes2 / sampsize,
- sampsize);
+ memcpy(lpvPtr2, (char *)data + dwBytes1, dwBytes2);
write_offset+=dwBytes1+dwBytes2;
if(write_offset>=buffer_size)
@@ -432,7 +377,7 @@ static int control(int cmd, void *arg)
\param flags unused
\return 1=success 0=fail
*/
-static int init(int rate, int channels, int format, int flags)
+static int init(int rate, const struct mp_chmap *channels, int format, int flags)
{
int res;
if (!InitDirectSound()) return 0;
@@ -446,14 +391,17 @@ static int init(int rate, int channels, int format, int flags)
DSBUFFERDESC dsbdesc;
//check if the channel count and format is supported in general
- if (channels > FF_ARRAY_ELEMS(channel_mask)) {
+ 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");
+ mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: > 8 channel audio not yet supported\n");
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:
@@ -465,25 +413,24 @@ static int init(int rate, int channels, int format, int flags)
format=AF_FORMAT_S16_LE;
}
//fill global ao_data
- ao_data.channels = channels;
ao_data.samplerate = rate;
ao_data.format = format;
- ao_data.bps = channels * rate * (af_fmt2bits(format)>>3);
+ ao_data.bps = ao_data.channels.num * rate * (af_fmt2bits(format)>>3);
if(ao_data.buffersize==-1) ao_data.buffersize = ao_data.bps; // space for 1 sec
- mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Samplerate:%iHz Channels:%i Format:%s\n", rate, channels, af_fmt2str_short(format));
+ mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Samplerate:%iHz Channels:%i Format:%s\n", rate, ao_data.channels.num, af_fmt2str_short(format));
mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Buffersize:%d bytes (%d msec)\n", ao_data.buffersize, ao_data.buffersize / ao_data.bps * 1000);
//fill waveformatex
ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE));
- wformat.Format.cbSize = (channels > 2) ? sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) : 0;
- wformat.Format.nChannels = channels;
+ wformat.Format.cbSize = (ao_data.channels.num > 2) ? sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) : 0;
+ wformat.Format.nChannels = ao_data.channels.num;
wformat.Format.nSamplesPerSec = rate;
if (AF_FORMAT_IS_AC3(format)) {
wformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
wformat.Format.wBitsPerSample = 16;
wformat.Format.nBlockAlign = 4;
} else {
- wformat.Format.wFormatTag = (channels > 2) ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM;
+ wformat.Format.wFormatTag = (ao_data.channels.num > 2) ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM;
wformat.Format.wBitsPerSample = af_fmt2bits(format);
wformat.Format.nBlockAlign = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3);
}
@@ -503,8 +450,8 @@ static int init(int rate, int channels, int format, int flags)
| DSBCAPS_GLOBALFOCUS /** Allows background playing */
| DSBCAPS_CTRLVOLUME; /** volume control enabled */
- if (channels > 2) {
- wformat.dwChannelMask = channel_mask[channels - 1];
+ if (ao_data.channels.num > 2) {
+ wformat.dwChannelMask = mp_chmap_to_waveext(&ao_data.channels);
wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample;
// Needed for 5.1 on emu101k - shit soundblaster
diff --git a/audio/out/ao_jack.c b/audio/out/ao_jack.c
index b75122dc17..aea64ee02c 100644
--- a/audio/out/ao_jack.c
+++ b/audio/out/ao_jack.c
@@ -202,7 +202,8 @@ static void print_help (void)
);
}
-static int init(int rate, int channels, int format, int flags) {
+static int init(int rate, const struct mp_chmap *channels, int format, int flags)
+{
const char **matching_ports = NULL;
char *port_name = NULL;
char *client_name = NULL;
@@ -222,8 +223,9 @@ static int init(int rate, int channels, int format, int flags) {
print_help();
return 0;
}
- if (channels > MAX_CHANS) {
- mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] Invalid number of channels: %i\n", channels);
+ if (ao_data.channels.num > MAX_CHANS) {
+ mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] Invalid number of channels: %i\n",
+ ao_data.channels.num);
goto err_out;
}
if (!client_name) {
@@ -249,9 +251,9 @@ static int init(int rate, int channels, int format, int flags) {
goto err_out;
}
i = 1;
+ num_ports = ao_data.channels.num;
while (matching_ports[i]) i++;
- if (channels > i) channels = i;
- num_ports = channels;
+ if (num_ports > i) num_ports = i;
// create out output ports
for (i = 0; i < num_ports; i++) {
@@ -281,10 +283,11 @@ static int init(int rate, int channels, int format, int flags) {
/ (float)rate;
callback_interval = 0;
- ao_data.channels = channels;
+ mp_chmap_from_channels(&ao_data.channels, num_ports);
+ mp_chmap_reorder_to_alsa(&ao_data.channels); // what order does hack use?
ao_data.samplerate = rate;
ao_data.format = AF_FORMAT_FLOAT_NE;
- ao_data.bps = channels * rate * sizeof(float);
+ ao_data.bps = ao_data.channels.num * rate * sizeof(float);
ao_data.buffersize = CHUNK_SIZE * NUM_CHUNKS;
ao_data.outburst = CHUNK_SIZE;
free(matching_ports);
diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c
index 062d1b928b..0b989224c4 100644
--- a/audio/out/ao_lavc.c
+++ b/audio/out/ao_lavc.c
@@ -101,7 +101,10 @@ static int init(struct ao *ao, char *params)
ac->stream->codec->time_base.den = ao->samplerate;
ac->stream->codec->sample_rate = ao->samplerate;
- ac->stream->codec->channels = ao->channels;
+
+ 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);
ac->stream->codec->sample_fmt = AV_SAMPLE_FMT_NONE;
@@ -243,36 +246,6 @@ out_takefirst:
ac->stream->codec->bits_per_raw_sample = ac->sample_size * 8;
- switch (ao->channels) {
- case 1:
- ac->stream->codec->channel_layout = AV_CH_LAYOUT_MONO;
- break;
- case 2:
- ac->stream->codec->channel_layout = AV_CH_LAYOUT_STEREO;
- break;
- /* someone please check if these are what mplayer normally assumes
- case 3:
- ac->stream->codec->channel_layout = AV_CH_LAYOUT_SURROUND;
- break;
- case 4:
- ac->stream->codec->channel_layout = AV_CH_LAYOUT_2_2;
- break;
- */
- case 5:
- ac->stream->codec->channel_layout = AV_CH_LAYOUT_5POINT0;
- break;
- case 6:
- ac->stream->codec->channel_layout = AV_CH_LAYOUT_5POINT1;
- break;
- case 8:
- ac->stream->codec->channel_layout = AV_CH_LAYOUT_7POINT1;
- break;
- default:
- mp_msg(MSGT_ENCODE, MSGL_ERR,
- "ao-lavc: unknown channel layout; hoping for the best\n");
- break;
- }
-
if (encode_lavc_open_codec(ao->encode_lavc_ctx, ac->stream) < 0)
return -1;
@@ -282,11 +255,12 @@ out_takefirst:
if (ac->pcmhack) {
ac->aframesize = 16384; // "enough"
- ac->buffer_size = ac->aframesize * ac->pcmhack * ao->channels * 2 + 200;
+ ac->buffer_size =
+ ac->aframesize * ac->pcmhack * ao->channels.num * 2 + 200;
} else {
ac->aframesize = ac->stream->codec->frame_size;
- ac->buffer_size = ac->aframesize * ac->sample_size * ao->channels * 2 +
- 200;
+ ac->buffer_size =
+ ac->aframesize * ac->sample_size * ao->channels.num * 2 + 200;
}
if (ac->buffer_size < FF_MIN_BUFFER_SIZE)
ac->buffer_size = FF_MIN_BUFFER_SIZE;
@@ -304,10 +278,10 @@ out_takefirst:
ac->offset_left = ac->offset;
//fill_ao_data:
- ao->outburst = ac->aframesize * ac->sample_size * ao->channels *
- ac->framecount;
+ ao->outburst =
+ ac->aframesize * ac->sample_size * ao->channels.num * ac->framecount;
ao->buffersize = ao->outburst * 2;
- ao->bps = ao->channels * ao->samplerate * ac->sample_size;
+ ao->bps = ao->channels.num * ao->samplerate * ac->sample_size;
ao->untimed = true;
ao->priv = ac;
@@ -346,12 +320,12 @@ static void uninit(struct ao *ao, bool cut_audio)
double pts = ao->pts + ac->offset / (double) ao->samplerate;
if (ao->buffer.len > 0) {
void *paddingbuf = talloc_size(ao,
- ac->aframesize * ao->channels * ac->sample_size);
+ ac->aframesize * ao->channels.num * ac->sample_size);
memcpy(paddingbuf, ao->buffer.start, ao->buffer.len);
fill_with_padding((char *) paddingbuf + ao->buffer.len,
- (ac->aframesize * ao->channels * ac->sample_size
- - ao->buffer.len) / ac->sample_size,
- ac->sample_size, ac->sample_padding);
+ (ac->aframesize * ao->channels.num * ac->sample_size -
+ ao->buffer.len) / ac->sample_size,
+ ac->sample_size, ac->sample_padding);
encode(ao, pts, paddingbuf);
pts += ac->aframesize / (double) ao->samplerate;
talloc_free(paddingbuf);
@@ -381,12 +355,6 @@ static int encode(struct ao *ao, double apts, void *data)
int status, gotpacket;
ac->aframecount++;
- if (data && (ao->channels == 5 || ao->channels == 6 || ao->channels == 8)) {
- reorder_channel_nch(data, AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
- AF_CHANNEL_LAYOUT_LAVC_DEFAULT,
- ao->channels,
- ac->aframesize * ao->channels, ac->sample_size);
- }
if (data)
ectx->audio_pts_offset = realapts - apts;
@@ -400,12 +368,18 @@ static int encode(struct ao *ao, double apts, void *data)
frame->nb_samples = ac->aframesize;
if (ac->planarize) {
- void *data2 = talloc_size(ao, ac->aframesize * ao->channels * ac->sample_size);
- reorder_to_planar(data2, data, ac->sample_size, ao->channels, ac->aframesize);
+ void *data2 = talloc_size(ao, ac->aframesize * ao->channels.num *
+ ac->sample_size);
+ reorder_to_planar(data2, data, ac->sample_size, ao->channels.num,
+ ac->aframesize);
data = data2;
}
- if (avcodec_fill_audio_frame(frame, ao->channels, ac->stream->codec->sample_fmt, data, ac->aframesize * ao->channels * ac->sample_size, 1)) {
+ size_t audiolen = ac->aframesize * ao->channels.num * ac->sample_size;
+ if (avcodec_fill_audio_frame(frame, ao->channels.num,
+ ac->stream->codec->sample_fmt, data,
+ audiolen, 1))
+ {
mp_msg(MSGT_ENCODE, MSGL_ERR, "ao-lavc: error filling\n");
return -1;
}
@@ -512,7 +486,7 @@ static int play(struct ao *ao, void *data, int len, int flags)
double pts = ao->pts;
double outpts;
- len /= ac->sample_size * ao->channels;
+ len /= ac->sample_size * ao->channels.num;
if (!encode_lavc_start(ectx)) {
mp_msg(MSGT_ENCODE, MSGL_WARN,
@@ -581,7 +555,7 @@ static int play(struct ao *ao, void *data, int len, int flags)
if (ac->offset_left <= -len) {
// skip whole frame
ac->offset_left += len;
- return len * ac->sample_size * ao->channels;
+ return len * ac->sample_size * ao->channels.num;
} else {
// skip part of this frame, buffer/encode the rest
bufpos -= ac->offset_left;
@@ -592,11 +566,11 @@ static int play(struct ao *ao, void *data, int len, int flags)
// make a temporary buffer, filled with zeroes at the start
// (don't worry, only happens once)
- paddingbuf = talloc_size(ac, ac->sample_size * ao->channels *
+ paddingbuf = talloc_size(ac, ac->sample_size * ao->channels.num *
(ac->offset_left + len));
fill_with_padding(paddingbuf, ac->offset_left, ac->sample_size,
ac->sample_padding);
- data = (char *) paddingbuf + ac->sample_size * ao->channels *
+ data = (char *) paddingbuf + ac->sample_size * ao->channels.num *
ac->offset_left;
bufpos -= ac->offset_left; // yes, negative!
ptsoffset += ac->offset_left;
@@ -639,7 +613,7 @@ static int play(struct ao *ao, void *data, int len, int flags)
while (len - bufpos >= ac->aframesize) {
encode(ao,
outpts + (bufpos + ptsoffset) / (double) ao->samplerate + encode_lavc_getoffset(ectx, ac->stream),
- (char *) data + ac->sample_size * bufpos * ao->channels);
+ (char *) data + ac->sample_size * bufpos * ao->channels.num);
bufpos += ac->aframesize;
}
@@ -655,7 +629,7 @@ static int play(struct ao *ao, void *data, int len, int flags)
ectx->next_in_pts = nextpts;
}
- return bufpos * ac->sample_size * ao->channels;
+ return bufpos * ac->sample_size * ao->channels.num;
}
const struct ao_driver audio_out_lavc = {
diff --git a/audio/out/ao_null.c b/audio/out/ao_null.c
index 102f0a7013..f6d7bb0c5f 100644
--- a/audio/out/ao_null.c
+++ b/audio/out/ao_null.c
@@ -49,10 +49,10 @@ static int init(struct ao *ao, char *params)
struct priv *priv = talloc_zero(ao, struct priv);
ao->priv = priv;
int samplesize = af_fmt2bits(ao->format) / 8;
- ao->outburst = 256 * ao->channels * samplesize;
+ ao->outburst = 256 * ao->channels.num * samplesize;
// A "buffer" for about 0.2 seconds of audio
ao->buffersize = (int)(ao->samplerate * 0.2 / 256 + 1) * ao->outburst;
- ao->bps = ao->channels * ao->samplerate * samplesize;
+ ao->bps = ao->channels.num * ao->samplerate * samplesize;
priv->last_time = GetTimer();
return 0;
diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c
index 157cf93ac4..e6e1369a2f 100644
--- a/audio/out/ao_openal.c
+++ b/audio/out/ao_openal.c
@@ -109,7 +109,9 @@ static void list_devices(void) {
}
}
-static int init(int rate, int channels, int format, int flags) {
+static int init(int rate, const struct mp_chmap *channels, int format,
+ int flags)
+{
float position[3] = {0, 0, 0};
float direction[6] = {0, 0, 1, 0, -1, 0};
float sppos[MAX_CHANS][3] = {
@@ -137,8 +139,9 @@ static int init(int rate, int channels, int format, int flags) {
list_devices();
goto err_out;
}
- if (channels > MAX_CHANS) {
- mp_msg(MSGT_AO, MSGL_FATAL, "[OpenAL] Invalid number of channels: %i\n", channels);
+ if (ao_data.channels.num > MAX_CHANS) {
+ mp_msg(MSGT_AO, MSGL_FATAL, "[OpenAL] Invalid number of channels: %i\n",
+ ao_data.channels.num);
goto err_out;
}
dev = alcOpenDevice(device);
@@ -150,25 +153,25 @@ static int init(int rate, int channels, int format, int flags) {
alcMakeContextCurrent(ctx);
alListenerfv(AL_POSITION, position);
alListenerfv(AL_ORIENTATION, direction);
- alGenSources(channels, sources);
- for (i = 0; i < channels; i++) {
+ alGenSources(ao_data.channels.num, sources);
+ for (i = 0; i < ao_data.channels.num; i++) {
cur_buf[i] = 0;
unqueue_buf[i] = 0;
alGenBuffers(NUM_BUF, buffers[i]);
alSourcefv(sources[i], AL_POSITION, sppos[i]);
alSource3f(sources[i], AL_VELOCITY, 0, 0, 0);
}
- if (channels == 1)
+ if (ao_data.channels.num == 1)
alSource3f(sources[0], AL_POSITION, 0, 0, 1);
- ao_data.channels = channels;
alcGetIntegerv(dev, ALC_FREQUENCY, 1, &freq);
if (alcGetError(dev) == ALC_NO_ERROR && freq)
rate = freq;
ao_data.samplerate = rate;
ao_data.format = AF_FORMAT_S16_NE;
- ao_data.bps = channels * rate * 2;
+ ao_data.bps = ao_data.channels.num * rate * 2;
ao_data.buffersize = CHUNK_SIZE * NUM_BUF;
- ao_data.outburst = channels * CHUNK_SIZE;
+ ao_data.outburst = ao_data.channels.num * CHUNK_SIZE;
+ mp_chmap_reorder_to_alsa(&ao_data.channels); // sppos[][] matrix is for ALSA
tmpbuf = malloc(CHUNK_SIZE);
free(device);
return 1;
@@ -200,7 +203,7 @@ static void uninit(int immed) {
static void unqueue_buffers(void) {
ALint p;
int s;
- for (s = 0; s < ao_data.channels; s++) {
+ for (s = 0; s < ao_data.channels.num; s++) {
int till_wrap = NUM_BUF - unqueue_buf[s];
alGetSourcei(sources[s], AL_BUFFERS_PROCESSED, &p);
if (p >= till_wrap) {
@@ -219,7 +222,7 @@ static void unqueue_buffers(void) {
* \brief stop playing and empty buffers (for seeking/pause)
*/
static void reset(void) {
- alSourceStopv(ao_data.channels, sources);
+ alSourceStopv(ao_data.channels.num, sources);
unqueue_buffers();
}
@@ -227,14 +230,14 @@ static void reset(void) {
* \brief stop playing, keep buffers (for pause)
*/
static void audio_pause(void) {
- alSourcePausev(ao_data.channels, sources);
+ alSourcePausev(ao_data.channels.num, sources);
}
/**
* \brief resume playing, after audio_pause()
*/
static void audio_resume(void) {
- alSourcePlayv(ao_data.channels, sources);
+ alSourcePlayv(ao_data.channels.num, sources);
}
static int get_space(void) {
@@ -243,7 +246,7 @@ static int get_space(void) {
alGetSourcei(sources[0], AL_BUFFERS_QUEUED, &queued);
queued = NUM_BUF - queued - 3;
if (queued < 0) return 0;
- return queued * CHUNK_SIZE * ao_data.channels;
+ return queued * CHUNK_SIZE * ao_data.channels.num;
}
/**
@@ -254,22 +257,22 @@ static int play(void *data, int len, int flags) {
int i, j, k;
int ch;
int16_t *d = data;
- len /= ao_data.channels * CHUNK_SIZE;
+ len /= ao_data.channels.num * CHUNK_SIZE;
for (i = 0; i < len; i++) {
- for (ch = 0; ch < ao_data.channels; ch++) {
- for (j = 0, k = ch; j < CHUNK_SIZE / 2; j++, k += ao_data.channels)
+ for (ch = 0; ch < ao_data.channels.num; ch++) {
+ for (j = 0, k = ch; j < CHUNK_SIZE / 2; j++, k += ao_data.channels.num)
tmpbuf[j] = d[k];
alBufferData(buffers[ch][cur_buf[ch]], AL_FORMAT_MONO16, tmpbuf,
CHUNK_SIZE, ao_data.samplerate);
alSourceQueueBuffers(sources[ch], 1, &buffers[ch][cur_buf[ch]]);
cur_buf[ch] = (cur_buf[ch] + 1) % NUM_BUF;
}
- d += ao_data.channels * CHUNK_SIZE / 2;
+ d += ao_data.channels.num * CHUNK_SIZE / 2;
}
alGetSourcei(sources[0], AL_SOURCE_STATE, &state);
if (state != AL_PLAYING) // checked here in case of an underrun
- alSourcePlayv(ao_data.channels, sources);
- return len * ao_data.channels * CHUNK_SIZE;
+ alSourcePlayv(ao_data.channels.num, sources);
+ return len * ao_data.channels.num * CHUNK_SIZE;
}
static float get_delay(void) {
diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c
index fa8eccdeea..805a14cd8f 100644
--- a/audio/out/ao_oss.c
+++ b/audio/out/ao_oss.c
@@ -221,12 +221,12 @@ static int control(int cmd,void *arg){
// open & setup audio device
// return: 1=success 0=fail
-static int init(int rate,int channels,int format,int flags){
+static int init(int rate,const struct mp_chmap *channels,int format,int flags){
char *mixer_channels [SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
int oss_format;
char *mdev = mixer_device, *mchan = mixer_channel;
- mp_msg(MSGT_AO,MSGL_V,"ao2: %d Hz %d chans %s\n",rate,channels,
+ mp_msg(MSGT_AO,MSGL_V,"ao2: %d Hz %d chans %s\n",rate,ao_data.channels.num,
af_fmt2str_short(format));
if (ao_subdevice) {
@@ -339,25 +339,27 @@ ac3_retry:
mp_msg(MSGT_AO,MSGL_V,"audio_setup: sample format: %s (requested: %s)\n",
af_fmt2str_short(ao_data.format), af_fmt2str_short(format));
- ao_data.channels = channels;
if(!AF_FORMAT_IS_AC3(format)) {
+ mp_chmap_reorder_to_alsa(&ao_data.channels);
+ int reqchannels = ao_data.channels.num;
// We only use SNDCTL_DSP_CHANNELS for >2 channels, in case some drivers don't have it
- if (ao_data.channels > 2) {
- if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &ao_data.channels) == -1 ||
- ao_data.channels != channels ) {
- mp_tmsg(MSGT_AO,MSGL_ERR,"[AO OSS] audio_setup: Failed to set audio device to %d channels.\n", channels);
+ if (reqchannels > 2) {
+ int nchannels = reqchannels;
+ if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &nchannels) == -1 ||
+ nchannels != reqchannels ) {
+ mp_tmsg(MSGT_AO,MSGL_ERR,"[AO OSS] audio_setup: Failed to set audio device to %d channels.\n", reqchannels);
return 0;
}
}
else {
- int c = ao_data.channels-1;
+ int c = reqchannels-1;
if (ioctl (audio_fd, SNDCTL_DSP_STEREO, &c) == -1) {
- mp_tmsg(MSGT_AO,MSGL_ERR,"[AO OSS] audio_setup: Failed to set audio device to %d channels.\n", ao_data.channels);
+ mp_tmsg(MSGT_AO,MSGL_ERR,"[AO OSS] audio_setup: Failed to set audio device to %d channels.\n", reqchannels);
return 0;
}
- ao_data.channels=c+1;
+ mp_chmap_from_channels(&ao_data.channels, c + 1);
}
- mp_msg(MSGT_AO,MSGL_V,"audio_setup: using %d channels (requested: %d)\n", ao_data.channels, channels);
+ mp_msg(MSGT_AO,MSGL_V,"audio_setup: using %d channels (requested: %d)\n", ao_data.channels.num, reqchannels);
// set rate
ao_data.samplerate=rate;
ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_data.samplerate);
@@ -403,7 +405,7 @@ ac3_retry:
#endif
}
- ao_data.bps=ao_data.channels;
+ ao_data.bps=ao_data.channels.num;
switch (ao_data.format & AF_FORMAT_BITS_MASK) {
case AF_FORMAT_8BIT:
break;
@@ -459,10 +461,10 @@ static void reset(void){
ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_data.samplerate);
ioctl (audio_fd, SNDCTL_DSP_SETFMT, &oss_format);
if(!AF_FORMAT_IS_AC3(ao_data.format)) {
- if (ao_data.channels > 2)
- ioctl (audio_fd, SNDCTL_DSP_CHANNELS, &ao_data.channels);
+ if (ao_data.channels.num > 2)
+ ioctl (audio_fd, SNDCTL_DSP_CHANNELS, &ao_data.channels.num);
else {
- int c = ao_data.channels-1;
+ int c = ao_data.channels.num-1;
ioctl (audio_fd, SNDCTL_DSP_STEREO, &c);
}
ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_data.samplerate);
diff --git a/audio/out/ao_pcm.c b/audio/out/ao_pcm.c
index 5b3cc94395..22d40671cb 100644
--- a/audio/out/ao_pcm.c
+++ b/audio/out/ao_pcm.c
@@ -69,7 +69,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 = ao->channels >= 5 && ao->channels <= 8;
+ bool use_waveex = true;
uint16_t fmt = ao->format == AF_FORMAT_FLOAT_LE ?
WAV_ID_FLOAT_PCM : WAV_ID_PCM;
uint32_t fmt_chunk_size = use_waveex ? 40 : 16;
@@ -86,30 +86,17 @@ static void write_wave_header(struct ao *ao, FILE *fp, uint64_t data_length)
fput32le(WAV_ID_FMT, fp);
fput32le(fmt_chunk_size, fp);
fput16le(use_waveex ? WAV_ID_FORMAT_EXTENSIBLE : fmt, fp);
- fput16le(ao->channels, fp);
+ fput16le(ao->channels.num, fp);
fput32le(ao->samplerate, fp);
fput32le(ao->bps, fp);
- fput16le(ao->channels * (bits / 8), fp);
+ fput16le(ao->channels.num * (bits / 8), fp);
fput16le(bits, fp);
if (use_waveex) {
// Extension chunk
fput16le(22, fp);
fput16le(bits, fp);
- switch (ao->channels) {
- case 5:
- fput32le(0x0607, fp); // L R C Lb Rb
- break;
- case 6:
- fput32le(0x060f, fp); // L R C Lb Rb LFE
- break;
- case 7:
- fput32le(0x0727, fp); // L R C Cb Ls Rs LFE
- break;
- case 8:
- fput32le(0x063f, fp); // L R C Lb Rb Ls Rs LFE
- break;
- }
+ fput32le(mp_chmap_to_waveext(&ao->channels), fp);
// 2 bytes format + 14 bytes guid
fput32le(fmt, fp);
fput32le(0x00100000, fp);
@@ -159,14 +146,16 @@ static int init(struct ao *ao, char *params)
}
}
+ mp_chmap_reorder_to_waveext(&ao->channels);
+
ao->outburst = 65536;
- ao->bps = ao->channels * ao->samplerate * (af_fmt2bits(ao->format) / 8);
+ ao->bps = ao->channels.num * ao->samplerate * (af_fmt2bits(ao->format) / 8);
mp_tmsg(MSGT_AO, MSGL_INFO, "[AO PCM] File: %s (%s)\n"
"PCM: Samplerate: %d Hz Channels: %d Format: %s\n",
priv->outputfilename,
priv->waveheader ? "WAVE" : "RAW PCM", ao->samplerate,
- ao->channels, af_fmt2str_short(ao->format));
+ ao->channels.num, af_fmt2str_short(ao->format));
mp_tmsg(MSGT_AO, MSGL_INFO,
"[AO PCM] Info: Faster dumping is achieved with -no-video\n"
"[AO PCM] Info: To write WAVE files use -ao pcm:waveheader (default).\n");
@@ -222,13 +211,6 @@ static int play(struct ao *ao, void *data, int len, int flags)
{
struct priv *priv = ao->priv;
- if (ao->channels == 5 || ao->channels == 6 || ao->channels == 8) {
- int frame_size = af_fmt2bits(ao->format) / 8;
- len -= len % (frame_size * ao->channels);
- reorder_channel_nch(data, AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
- AF_CHANNEL_LAYOUT_WAVEEX_DEFAULT,
- ao->channels, len / frame_size, frame_size);
- }
fwrite(data, len, 1, priv->fp);
priv->data_length += len;
return len;
diff --git a/audio/out/ao_portaudio.c b/audio/out/ao_portaudio.c
index b0744e8f8a..0141e4796d 100644
--- a/audio/out/ao_portaudio.c
+++ b/audio/out/ao_portaudio.c
@@ -273,9 +273,11 @@ static int init(struct ao *ao, char *params)
if (pa_device == paNoDevice)
goto error_exit;
+ mp_chmap_reorder_to_alsa(&ao->channels);
+
PaStreamParameters sp = {
.device = pa_device,
- .channelCount = ao->channels,
+ .channelCount = ao->channels.num,
.suggestedLatency
= Pa_GetDeviceInfo(pa_device)->defaultHighOutputLatency,
};
@@ -298,7 +300,7 @@ static int init(struct ao *ao, char *params)
ao->format = fmt->mp_format;
sp.sampleFormat = fmt->pa_format;
- priv->framelen = ao->channels * (af_fmt2bits(ao->format) / 8);
+ priv->framelen = ao->channels.num * (af_fmt2bits(ao->format) / 8);
ao->bps = ao->samplerate * priv->framelen;
if (!check_pa_ret(Pa_IsFormatSupported(NULL, &sp, ao->samplerate)))
diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c
index bb5af6f851..7f3619386e 100644
--- a/audio/out/ao_pulse.c
+++ b/audio/out/ao_pulse.c
@@ -209,7 +209,7 @@ static int init(struct ao *ao, char *params)
priv->broken_pause = true;
}
- ss.channels = ao->channels;
+ ss.channels = ao->channels.num;
ss.rate = ao->samplerate;
const struct format_map *fmt_map = format_maps;
@@ -230,7 +230,9 @@ static int init(struct ao *ao, char *params)
goto fail;
}
+ mp_chmap_reorder_to_waveext(&ao->channels);
pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_WAVEEX);
+
ao->bps = pa_bytes_per_second(&ss);
if (!(priv->mainloop = pa_threaded_mainloop_new())) {
@@ -495,7 +497,7 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
const ao_control_vol_t *vol = arg;
struct pa_cvolume volume;
- pa_cvolume_reset(&volume, ao->channels);
+ pa_cvolume_reset(&volume, ao->channels.num);
if (volume.channels != 2)
pa_cvolume_set(&volume, volume.channels, VOL_MP2PA(vol->left));
else {
diff --git a/audio/out/ao_rsound.c b/audio/out/ao_rsound.c
index 7722bf19d2..004beb0867 100644
--- a/audio/out/ao_rsound.c
+++ b/audio/out/ao_rsound.c
@@ -121,8 +121,10 @@ static int init(struct ao *ao, char *params)
free(port);
}
+ mp_chmap_reorder_to_alsa(&ao->channels);
+
rsd_set_param(priv->rd, RSD_SAMPLERATE, &ao->samplerate);
- rsd_set_param(priv->rd, RSD_CHANNELS, &ao->channels);
+ rsd_set_param(priv->rd, RSD_CHANNELS, &ao->channels.num);
int rsd_format = set_format(ao);
rsd_set_param(priv->rd, RSD_FORMAT, &rsd_format);
@@ -132,7 +134,7 @@ static int init(struct ao *ao, char *params)
return -1;
}
- ao->bps = ao->channels * ao->samplerate * af_fmt2bits(ao->format) / 8;
+ ao->bps = ao->channels.num * ao->samplerate * af_fmt2bits(ao->format) / 8;
return 0;
}
diff --git a/audio/out/ao_sdl.c b/audio/out/ao_sdl.c
index 7cfb1ae1e2..c91b16e4bc 100644
--- a/audio/out/ao_sdl.c
+++ b/audio/out/ao_sdl.c
@@ -185,7 +185,7 @@ static int init(struct ao *ao, char *params)
#endif
}
desired.freq = ao->samplerate;
- desired.channels = ao->channels;
+ desired.channels = ao->channels.num;
desired.samples = FFMIN(32768, ceil_power_of_two(ao->samplerate * buflen));
desired.callback = audio_callback;
desired.userdata = ao;
@@ -237,8 +237,9 @@ static int init(struct ao *ao, char *params)
}
ao->samplerate = obtained.freq;
- ao->channels = obtained.channels;
- ao->bps = ao->channels * ao->samplerate * bytes;
+ 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;
priv->buffer = av_fifo_alloc(ao->buffersize);
diff --git a/audio/out/audio_out_internal.h b/audio/out/audio_out_internal.h
index f3e92dff66..7b863cfd21 100644
--- a/audio/out/audio_out_internal.h
+++ b/audio/out/audio_out_internal.h
@@ -20,11 +20,12 @@
#define MPLAYER_AUDIO_OUT_INTERNAL_H
#include "core/options.h"
+#include "ao.h"
// prototypes:
//static ao_info_t info;
static int control(int cmd, void *arg);
-static int init(int rate,int channels,int format,int flags);
+static int init(int rate,const struct mp_chmap *channels,int format,int flags);
static void uninit(int immed);
static void reset(void);
static int get_space(void);
diff --git a/core/mplayer.c b/core/mplayer.c
index 64c8e9555d..3f7df8ef36 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -1564,7 +1564,7 @@ void reinit_audio_chain(struct MPContext *mpctx)
mpctx->ao->format = opts->audio_output_format;
// Automatic downmix
if (opts->audio_output_channels == 2 && mpctx->sh_audio->channels != 2)
- mpctx->ao->channels = 2;
+ mp_chmap_from_channels(&mpctx->ao->channels, 2);
}
ao = mpctx->ao;
@@ -1591,7 +1591,7 @@ void reinit_audio_chain(struct MPContext *mpctx)
mp_msg(MSGT_CPLAYER, MSGL_INFO,
"AO: [%s] %dHz %dch %s (%d bytes per sample)\n",
ao->driver->info->short_name,
- ao->samplerate, ao->channels,
+ ao->samplerate, ao->channels.num,
af_fmt2str_short(ao->format),
af_fmt2bits(ao->format) / 8);
mp_msg(MSGT_CPLAYER, MSGL_V, "AO: Description: %s\nAO: Author: %s\n",
@@ -2160,7 +2160,7 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize)
ptsdiff = written_pts - mpctx->sh_video->pts - mpctx->delay
- mpctx->audio_delay;
bytes = ptsdiff * bps;
- bytes -= bytes % (ao->channels * af_fmt2bits(ao->format) / 8);
+ bytes -= bytes % (ao->channels.num * af_fmt2bits(ao->format) / 8);
// ogg demuxers give packets without timing
if (written_pts <= 1 && sh_audio->pts == MP_NOPTS_VALUE) {
@@ -2229,7 +2229,7 @@ static int fill_audio_out_buffers(struct MPContext *mpctx, double endpts)
bool partial_fill = false;
sh_audio_t * const sh_audio = mpctx->sh_audio;
bool modifiable_audio_format = !(ao->format & AF_FORMAT_SPECIAL_MASK);
- int unitsize = ao->channels * af_fmt2bits(ao->format) / 8;
+ int unitsize = ao->channels.num * af_fmt2bits(ao->format) / 8;
if (mpctx->paused)
playsize = 1; // just initialize things (audio pts at least)