mirror of
https://github.com/mpv-player/mpv
synced 2024-10-30 04:46:41 +01:00
b745c2d005
Until now, the audio chain could handle both little endian and big endian formats. This actually doesn't make much sense, since the audio API and the HW will most likely prefer native formats. Or at the very least, it should be trivial for audio drivers to do the byte swapping themselves. From now on, the audio chain contains native-endian formats only. All AOs and some filters are adjusted. af_convertsignendian.c is now wrongly named, but the filter name is adjusted. In some cases, the audio infrastructure was reused on the demuxer side, but that is relatively easy to rectify. This is a quite intrusive and radical change. It's possible that it will break some things (especially if they're obscure or not Linux), so watch out for regressions. It's probably still better to do it the bulldozer way, since slow transition and researching foreign platforms would take a lot of time and effort.
183 lines
4.2 KiB
C
183 lines
4.2 KiB
C
/*
|
|
* RSound audio output driver
|
|
*
|
|
* Copyright (C) 2011 Hans-Kristian Arntzen
|
|
*
|
|
* This file is part of mplayer2.
|
|
*
|
|
* mplayer2 is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* mplayer2 is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with mplayer2; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <rsound.h>
|
|
|
|
#include "talloc.h"
|
|
|
|
#include "options/m_option.h"
|
|
#include "osdep/timer.h"
|
|
#include "audio/format.h"
|
|
#include "ao.h"
|
|
#include "internal.h"
|
|
|
|
struct priv {
|
|
rsound_t *rd;
|
|
char *host;
|
|
char *port;
|
|
};
|
|
|
|
static int set_format(struct ao *ao)
|
|
{
|
|
int rsd_format;
|
|
|
|
switch (ao->format) {
|
|
case AF_FORMAT_U8:
|
|
rsd_format = RSD_U8;
|
|
break;
|
|
case AF_FORMAT_S8:
|
|
rsd_format = RSD_S8;
|
|
break;
|
|
case AF_FORMAT_S16:
|
|
rsd_format = RSD_S16_NE;
|
|
break;
|
|
case AF_FORMAT_U16:
|
|
rsd_format = RSD_U16_NE;
|
|
break;
|
|
case AF_FORMAT_S24:
|
|
case AF_FORMAT_U24:
|
|
rsd_format = RSD_S32_NE;
|
|
ao->format = AF_FORMAT_S32;
|
|
break;
|
|
case AF_FORMAT_S32:
|
|
rsd_format = RSD_S32_NE;
|
|
break;
|
|
case AF_FORMAT_U32:
|
|
rsd_format = RSD_U32_NE;
|
|
break;
|
|
default:
|
|
rsd_format = RSD_S16_NE;
|
|
ao->format = AF_FORMAT_S16;
|
|
}
|
|
|
|
return rsd_format;
|
|
}
|
|
|
|
static int init(struct ao *ao)
|
|
{
|
|
struct priv *priv = ao->priv;
|
|
|
|
if (rsd_init(&priv->rd) < 0)
|
|
return -1;
|
|
|
|
if (priv->host && priv->host[0])
|
|
rsd_set_param(priv->rd, RSD_HOST, priv->host);
|
|
|
|
if (priv->port && priv->port[0])
|
|
rsd_set_param(priv->rd, RSD_PORT, priv->port);
|
|
|
|
// Actual channel layout unknown.
|
|
struct mp_chmap_sel sel = {0};
|
|
mp_chmap_sel_add_waveext_def(&sel);
|
|
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) {
|
|
rsd_free(priv->rd);
|
|
return -1;
|
|
}
|
|
|
|
rsd_set_param(priv->rd, RSD_SAMPLERATE, (int[]) { ao->samplerate });
|
|
rsd_set_param(priv->rd, RSD_CHANNELS, (int[]) { ao->channels.num });
|
|
|
|
ao->format = af_fmt_from_planar(ao->format);
|
|
|
|
int rsd_format = set_format(ao);
|
|
rsd_set_param(priv->rd, RSD_FORMAT, &rsd_format);
|
|
|
|
if (rsd_start(priv->rd) < 0) {
|
|
rsd_free(priv->rd);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void uninit(struct ao *ao)
|
|
{
|
|
struct priv *priv = ao->priv;
|
|
|
|
rsd_stop(priv->rd);
|
|
rsd_free(priv->rd);
|
|
}
|
|
|
|
static void reset(struct ao *ao)
|
|
{
|
|
struct priv *priv = ao->priv;
|
|
rsd_stop(priv->rd);
|
|
rsd_start(priv->rd);
|
|
}
|
|
|
|
static void audio_pause(struct ao *ao)
|
|
{
|
|
struct priv *priv = ao->priv;
|
|
rsd_pause(priv->rd, 1);
|
|
}
|
|
|
|
static void audio_resume(struct ao *ao)
|
|
{
|
|
struct priv *priv = ao->priv;
|
|
rsd_pause(priv->rd, 0);
|
|
}
|
|
|
|
static int get_space(struct ao *ao)
|
|
{
|
|
struct priv *priv = ao->priv;
|
|
return rsd_get_avail(priv->rd) / ao->sstride;
|
|
}
|
|
|
|
static int play(struct ao *ao, void **data, int samples, int flags)
|
|
{
|
|
struct priv *priv = ao->priv;
|
|
return rsd_write(priv->rd, data[0], samples * ao->sstride) / ao->sstride;
|
|
}
|
|
|
|
static float get_delay(struct ao *ao)
|
|
{
|
|
struct priv *priv = ao->priv;
|
|
return rsd_delay_ms(priv->rd) / 1000.0;
|
|
}
|
|
|
|
#define OPT_BASE_STRUCT struct priv
|
|
|
|
const struct ao_driver audio_out_rsound = {
|
|
.description = "RSound output driver",
|
|
.name = "rsound",
|
|
.init = init,
|
|
.uninit = uninit,
|
|
.reset = reset,
|
|
.get_space = get_space,
|
|
.play = play,
|
|
.get_delay = get_delay,
|
|
.pause = audio_pause,
|
|
.resume = audio_resume,
|
|
.priv_size = sizeof(struct priv),
|
|
.options = (const struct m_option[]) {
|
|
OPT_STRING("host", host, 0),
|
|
OPT_STRING("port", port, 0),
|
|
{0}
|
|
},
|
|
};
|
|
|