mirror of
https://github.com/mpv-player/mpv
synced 2025-02-21 07:16:56 +00:00
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.
This commit is contained in:
parent
37325f2796
commit
aea2328906
@ -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!
|
||||
|
@ -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 */
|
||||
|
@ -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"))) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)))
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user