From aea2328906fc754c0d0cdea57c60d71522ae99a5 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 5 Apr 2013 23:06:22 +0200 Subject: audio/out: switch to channel map This actually breaks audio for 5/6/8 channels. There's no reordering done yet. The actual reordering will be done inside of af_lavrresample and has to be made part of the format negotiation. --- audio/decode/dec_audio.c | 7 ++-- audio/decode/dec_audio.h | 4 +- audio/mixer.c | 2 +- audio/out/ao.c | 2 +- audio/out/ao.h | 5 ++- audio/out/ao_alsa.c | 31 +++++++-------- audio/out/ao_coreaudio.c | 15 +++++--- audio/out/ao_dsound.c | 83 ++++++++-------------------------------- audio/out/ao_jack.c | 17 +++++---- audio/out/ao_lavc.c | 86 +++++++++++++++--------------------------- audio/out/ao_null.c | 4 +- audio/out/ao_openal.c | 43 +++++++++++---------- audio/out/ao_oss.c | 32 ++++++++-------- audio/out/ao_pcm.c | 34 ++++------------- audio/out/ao_portaudio.c | 6 ++- audio/out/ao_pulse.c | 6 ++- audio/out/ao_rsound.c | 6 ++- audio/out/ao_sdl.c | 7 ++-- audio/out/audio_out_internal.h | 3 +- 19 files changed, 158 insertions(+), 235 deletions(-) (limited to 'audio') 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); -- cgit v1.2.3