ports/multimedia/mplayer/files/patch-libao2_ao__oss.c
2021-07-04 23:42:46 +02:00

146 lines
4.3 KiB
C

--- libao2/ao_oss.c.orig 2021-04-15 19:26:53 UTC
+++ libao2/ao_oss.c
@@ -57,6 +57,8 @@ static const ao_info_t info =
""
};
+static int volume = -1;
+
/* Support for >2 output channels added 2001-11-25 - Steve Davies <steve@daviesfam.org> */
LIBAO_EXTERN(oss)
@@ -73,6 +75,11 @@ static int format2oss(int format)
case AF_FORMAT_S16_BE: return AFMT_S16_BE;
#ifdef AFMT_S24_PACKED
case AF_FORMAT_S24_LE: return AFMT_S24_PACKED;
+#elif defined(__FreeBSD__) && defined(AFMT_S24_LE)
+ case AF_FORMAT_U24_LE: return AFMT_U24_LE;
+ case AF_FORMAT_U24_BE: return AFMT_U24_BE;
+ case AF_FORMAT_S24_LE: return AFMT_S24_LE;
+ case AF_FORMAT_S24_BE: return AFMT_S24_BE;
#endif
#ifdef AFMT_U32_LE
case AF_FORMAT_U32_LE: return AFMT_U32_LE;
@@ -116,6 +123,11 @@ static int oss2format(int format)
case AFMT_S16_BE: return AF_FORMAT_S16_BE;
#ifdef AFMT_S24_PACKED
case AFMT_S24_PACKED: return AF_FORMAT_S24_LE;
+#elif defined(__FreeBSD__) && defined(AFMT_S24_LE)
+ case AFMT_U24_LE: return AF_FORMAT_U24_LE;
+ case AFMT_U24_BE: return AF_FORMAT_U24_BE;
+ case AFMT_S24_LE: return AF_FORMAT_S24_LE;
+ case AFMT_S24_BE: return AF_FORMAT_S24_BE;
#endif
#ifdef AFMT_U32_LE
case AFMT_U32_LE: return AF_FORMAT_U32_LE;
@@ -217,6 +229,48 @@ static int control(int cmd,void *arg){
return CONTROL_UNKNOWN;
}
+static void setfragment(int audio_fd)
+{
+ int buffer_bytes = ao_data.channels * ao_data.samplerate;
+ int block_size = 0;
+
+ switch (ao_data.format & AF_FORMAT_BITS_MASK) {
+ case AF_FORMAT_8BIT:
+ break;
+ case AF_FORMAT_16BIT:
+ buffer_bytes *= 2;
+ break;
+ case AF_FORMAT_24BIT:
+ buffer_bytes *= 3;
+ break;
+ case AF_FORMAT_32BIT:
+ buffer_bytes *= 4;
+ break;
+ }
+ buffer_bytes *= 0.050;
+
+ if(ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &block_size)==0){
+ int setfrag;
+ /* make block size power of two */
+ while (block_size & (block_size - 1))
+ block_size += block_size & ~(block_size - 1);
+ /* set number of fragments */
+ setfrag = ((buffer_bytes + block_size - 1) / block_size) << 16;
+ /* need at least double buffering */
+ if (setfrag < (2 << 16))
+ setfrag = (2 << 16);
+ /* set block size in power of two */
+ while (block_size) {
+ setfrag++;
+ block_size /= 2;
+ }
+ /* try to set a total buffer of 50ms */
+ if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &setfrag)==-1){
+ mp_msg(MSGT_AO,MSGL_V,"audio_setup: setfragment %d failed\n", setfrag);
+ }
+ }
+}
+
// open & setup audio device
// return: 1=success 0=fail
static int init(int rate,int channels,int format,int flags){
@@ -364,6 +418,7 @@ ac3_retry:
mp_msg(MSGT_AO,MSGL_WARN, "OSS: Failed setting sample-rate %i %s\n", rate, strerror(errno));
mp_msg(MSGT_AO,MSGL_V,"audio_setup: using %d Hz samplerate (requested: %d)\n",ao_data.samplerate,rate);
}
+ setfragment(audio_fd);
if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)==-1){
int r=0;
@@ -441,10 +496,30 @@ static void uninit(int immed){
audio_fd = -1;
}
+static void savevol(void){
+ int fd;
+ if (volume < 0) {
+ if ((fd = open(oss_mixer_device, O_RDONLY)) >= 0) {
+ ioctl(fd, MIXER_READ(oss_mixer_channel), &volume);
+ close(fd);
+ }
+ }
+}
+
+static void restorevol(void){
+ int fd;
+ if ((fd = open(oss_mixer_device, O_RDONLY)) >= 0) {
+ ioctl(fd, MIXER_WRITE(oss_mixer_channel), &volume);
+ close(fd);
+ }
+ volume = -1;
+}
+
// stop playing and empty buffers (for seeking/pause)
static void reset(void){
int fail = 0;
int oss_format;
+ savevol();
uninit(1);
audio_fd=open(dsp, O_WRONLY);
if(audio_fd < 0){
@@ -456,6 +531,7 @@ static void reset(void){
fcntl(audio_fd, F_SETFD, FD_CLOEXEC);
#endif
+ ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_data.samplerate);
oss_format = format2oss(ao_data.format);
if(AF_FORMAT_IS_AC3(ao_data.format))
fail |= ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_data.samplerate) == -1;
@@ -471,11 +547,14 @@ static void reset(void){
}
if (fail)
mp_msg(MSGT_AO,MSGL_WARN, "OSS: Reset failed\n");
+ setfragment(audio_fd);
+ restorevol();
}
// stop playing, keep buffers (for pause)
static void audio_pause(void)
{
+ savevol();
prepause_space = get_space();
uninit(1);
}