mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
Add OSS Mixer support.
This commit is contained in:
parent
0f449c2394
commit
aba14813c0
@ -1,7 +1,10 @@
|
|||||||
User johns
|
User johns
|
||||||
Date:
|
Date:
|
||||||
|
|
||||||
New audio driver oss.
|
Release Version 0.1.5
|
||||||
|
Adds OSS mixer support.
|
||||||
|
Fix bug: audio new stream is not thread safe.
|
||||||
|
New audio driver OSS.
|
||||||
Fix bug: needed down sampling of 3/5/6 to 2 channels not reported.
|
Fix bug: needed down sampling of 3/5/6 to 2 channels not reported.
|
||||||
Search audio sync inside PES packets, for insane dvb streams.
|
Search audio sync inside PES packets, for insane dvb streams.
|
||||||
Use only the needed number of surfaces.
|
Use only the needed number of surfaces.
|
||||||
|
@ -85,6 +85,8 @@ Setup: environment
|
|||||||
oss dsp device name
|
oss dsp device name
|
||||||
OSS_MIXERDEV=/dev/mixer
|
OSS_MIXERDEV=/dev/mixer
|
||||||
oss mixer device name
|
oss mixer device name
|
||||||
|
OSS_MIXER_CHANNEL=pcm
|
||||||
|
oss mixer channel name
|
||||||
|
|
||||||
Setup: /etc/vdr/setup.conf
|
Setup: /etc/vdr/setup.conf
|
||||||
------
|
------
|
||||||
|
2
Todo
2
Todo
@ -68,6 +68,8 @@ audio/alsa:
|
|||||||
CodecAudioOpen can fail "can't open audio codec" and does Fatal exit.
|
CodecAudioOpen can fail "can't open audio codec" and does Fatal exit.
|
||||||
|
|
||||||
audio/oss:
|
audio/oss:
|
||||||
|
alsa oss emulation mixer "pcm" not working
|
||||||
|
ring buffer overflow with alsa oss emulation
|
||||||
|
|
||||||
playback of recording
|
playback of recording
|
||||||
play back is too fast
|
play back is too fast
|
||||||
|
122
audio.c
122
audio.c
@ -96,9 +96,9 @@
|
|||||||
// Variables
|
// Variables
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
static const char *AudioPCMDevice; ///< alsa PCM device name
|
static const char *AudioPCMDevice; ///< alsa/oss PCM device name
|
||||||
static const char *AudioMixerDevice; ///< alsa mixer device name
|
static const char *AudioMixerDevice; ///< alsa/oss mixer device name
|
||||||
static const char *AudioMixerChannel; ///< alsa mixer channel name
|
static const char *AudioMixerChannel; ///< alsa/oss mixer channel name
|
||||||
static volatile char AudioRunning; ///< thread running / stopped
|
static volatile char AudioRunning; ///< thread running / stopped
|
||||||
static int AudioPaused; ///< audio paused
|
static int AudioPaused; ///< audio paused
|
||||||
static unsigned AudioSampleRate; ///< audio sample rate in hz
|
static unsigned AudioSampleRate; ///< audio sample rate in hz
|
||||||
@ -635,7 +635,7 @@ static void AlsaInitMixer(void)
|
|||||||
AlsaMixer = alsa_mixer;
|
AlsaMixer = alsa_mixer;
|
||||||
AlsaMixerElem = alsa_mixer_elem;
|
AlsaMixerElem = alsa_mixer_elem;
|
||||||
} else {
|
} else {
|
||||||
Error(_("audio/alsa: can't open alsa mixer '%s'\n"), device);
|
Error(_("audio/alsa: can't open mixer '%s'\n"), device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -854,10 +854,14 @@ static int AlsaSetup(int *freq, int *channels)
|
|||||||
|
|
||||||
AlsaStartThreshold = snd_pcm_frames_to_bytes(AlsaPCMHandle, period_size);
|
AlsaStartThreshold = snd_pcm_frames_to_bytes(AlsaPCMHandle, period_size);
|
||||||
// min 333ms
|
// min 333ms
|
||||||
if (AlsaStartThreshold < (*freq * *channels * 2U) / 3) {
|
if (AlsaStartThreshold < (*freq * *channels * AudioBytesProSample) / 3U) {
|
||||||
AlsaStartThreshold = (*freq * *channels * 2U) / 3;
|
AlsaStartThreshold = (*freq * *channels * AudioBytesProSample) / 3U;
|
||||||
}
|
}
|
||||||
Debug(3, "audio/alsa: delay %u ms\n", (AlsaStartThreshold * 1000)
|
// no bigger, than the buffer
|
||||||
|
if (AlsaStartThreshold > RingBufferFreeBytes(AlsaRingBuffer)) {
|
||||||
|
AlsaStartThreshold = RingBufferFreeBytes(AlsaRingBuffer);
|
||||||
|
}
|
||||||
|
Info(_("audio/alsa: delay %u ms\n"), (AlsaStartThreshold * 1000)
|
||||||
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -926,6 +930,7 @@ static void AlsaExit(void)
|
|||||||
|
|
||||||
static int OssPcmFildes = -1; ///< pcm file descriptor
|
static int OssPcmFildes = -1; ///< pcm file descriptor
|
||||||
static int OssMixerFildes = -1; ///< mixer file descriptor
|
static int OssMixerFildes = -1; ///< mixer file descriptor
|
||||||
|
static int OssMixerChannel; ///< mixer channel index
|
||||||
static RingBuffer *OssRingBuffer; ///< audio ring buffer
|
static RingBuffer *OssRingBuffer; ///< audio ring buffer
|
||||||
static unsigned OssStartThreshold; ///< start play, if filled
|
static unsigned OssStartThreshold; ///< start play, if filled
|
||||||
|
|
||||||
@ -995,8 +1000,8 @@ static int OssPlayRingbuffer(void)
|
|||||||
if (n < bi.bytes) { // not enough bytes in ring buffer
|
if (n < bi.bytes) { // not enough bytes in ring buffer
|
||||||
bi.bytes = n;
|
bi.bytes = n;
|
||||||
}
|
}
|
||||||
if (!bi.bytes) { // full or buffer empty
|
if (bi.bytes <= 0) { // full or buffer empty
|
||||||
break;
|
break; // bi.bytes could become negative!
|
||||||
}
|
}
|
||||||
|
|
||||||
n = write(OssPcmFildes, p, bi.bytes);
|
n = write(OssPcmFildes, p, bi.bytes);
|
||||||
@ -1076,7 +1081,7 @@ static void OssInitPCM(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((fildes = open(device, O_WRONLY)) < 0) {
|
if ((fildes = open(device, O_WRONLY)) < 0) {
|
||||||
Error(_("audio/oss: can't open device '%s': %s\n"), device,
|
Error(_("audio/oss: can't open dsp device '%s': %s\n"), device,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1084,6 +1089,85 @@ static void OssInitPCM(void)
|
|||||||
OssPcmFildes = fildes;
|
OssPcmFildes = fildes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// OSS Mixer
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Set oss mixer volume (0-100)
|
||||||
|
**
|
||||||
|
** @param volume volume (0 .. 100)
|
||||||
|
*/
|
||||||
|
static void OssSetVolume(int volume)
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
|
||||||
|
if (OssMixerFildes != -1) {
|
||||||
|
v = (volume * 255) / 100;
|
||||||
|
v &= 0xff;
|
||||||
|
v = (v << 8) | v;
|
||||||
|
if (ioctl(OssMixerFildes, MIXER_WRITE(OssMixerChannel), &v) < 0) {
|
||||||
|
Error(_("audio/oss: ioctl(MIXER_WRITE): %s\n"), strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Mixer channel name table.
|
||||||
|
*/
|
||||||
|
static const char *OssMixerChannelNames[SOUND_MIXER_NRDEVICES] =
|
||||||
|
SOUND_DEVICE_NAMES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Initialize oss mixer.
|
||||||
|
*/
|
||||||
|
static void OssInitMixer(void)
|
||||||
|
{
|
||||||
|
const char *device;
|
||||||
|
const char *channel;
|
||||||
|
int fildes;
|
||||||
|
int devmask;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!(device = AudioMixerDevice)) {
|
||||||
|
if (!(device = getenv("OSS_MIXERDEV"))) {
|
||||||
|
device = "/dev/mixer";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(channel = AudioMixerChannel)) {
|
||||||
|
if (!(channel = getenv("OSS_MIXER_CHANNEL"))) {
|
||||||
|
channel = "pcm";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Debug(3, "audio/oss: mixer %s - %s open\n", device, channel);
|
||||||
|
|
||||||
|
if ((fildes = open(device, O_RDWR)) < 0) {
|
||||||
|
Error(_("audio/oss: can't open mixer device '%s': %s\n"), device,
|
||||||
|
strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// search channel name
|
||||||
|
if (ioctl(fildes, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) {
|
||||||
|
Error(_("audio/oss: ioctl(SOUND_MIXER_READ_DEVMASK): %s\n"),
|
||||||
|
strerror(errno));
|
||||||
|
close(fildes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < SOUND_MIXER_NRDEVICES; ++i) {
|
||||||
|
if (!strcasecmp(OssMixerChannelNames[i], channel)) {
|
||||||
|
if (devmask & (1 << i)) {
|
||||||
|
OssMixerFildes = fildes;
|
||||||
|
OssMixerChannel = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Error(_("audio/oss: channel '%s' not supported\n"), channel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Error(_("audio/oss: channel '%s' not found\n"), channel);
|
||||||
|
close(fildes);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// OSS API
|
// OSS API
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -1120,8 +1204,10 @@ static uint64_t OssGetDelay(void)
|
|||||||
/ (AudioSampleRate * AudioChannels * AudioBytesProSample);
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample);
|
||||||
pts += ((uint64_t) RingBufferUsedBytes(OssRingBuffer) * 90 * 1000)
|
pts += ((uint64_t) RingBufferUsedBytes(OssRingBuffer) * 90 * 1000)
|
||||||
/ (AudioSampleRate * AudioChannels * AudioBytesProSample);
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample);
|
||||||
|
if (pts > 600 * 90) {
|
||||||
Debug(4, "audio/oss: hw+sw delay %zd %" PRId64 " ms\n",
|
Debug(4, "audio/oss: hw+sw delay %zd %" PRId64 " ms\n",
|
||||||
RingBufferUsedBytes(OssRingBuffer), pts / 90);
|
RingBufferUsedBytes(OssRingBuffer), pts / 90);
|
||||||
|
}
|
||||||
|
|
||||||
return pts;
|
return pts;
|
||||||
}
|
}
|
||||||
@ -1211,7 +1297,7 @@ static int OssSetup(int *freq, int *channels)
|
|||||||
Error(_("audio/oss: ioctl(SNDCTL_DSP_GETOSPACE): %s\n"),
|
Error(_("audio/oss: ioctl(SNDCTL_DSP_GETOSPACE): %s\n"),
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
Info(_("audio/oss: %d bytes buffered\n"), bi.bytes);
|
Debug(3, "audio/oss: %d bytes buffered\n", bi.bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = -1;
|
tmp = -1;
|
||||||
@ -1226,8 +1312,16 @@ static int OssSetup(int *freq, int *channels)
|
|||||||
}
|
}
|
||||||
// start when enough bytes for initial write
|
// start when enough bytes for initial write
|
||||||
OssStartThreshold = bi.bytes + tmp;
|
OssStartThreshold = bi.bytes + tmp;
|
||||||
|
// min 333ms
|
||||||
|
if (OssStartThreshold < (*freq * *channels * AudioBytesProSample) / 3U) {
|
||||||
|
OssStartThreshold = (*freq * *channels * AudioBytesProSample) / 3U;
|
||||||
|
}
|
||||||
|
// no bigger, than the buffer
|
||||||
|
if (OssStartThreshold > RingBufferFreeBytes(OssRingBuffer)) {
|
||||||
|
OssStartThreshold = RingBufferFreeBytes(OssRingBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
Debug(3, "audio/alsa: delay %u ms\n", (OssStartThreshold * 1000)
|
Info(_("audio/oss: delay %u ms\n"), (OssStartThreshold * 1000)
|
||||||
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1242,7 +1336,7 @@ static void OssInit(void)
|
|||||||
OssRingBuffer = RingBufferNew(48000 * 8 * 2); // ~1s 8ch 16bit
|
OssRingBuffer = RingBufferNew(48000 * 8 * 2); // ~1s 8ch 16bit
|
||||||
|
|
||||||
OssInitPCM();
|
OssInitPCM();
|
||||||
// OssInitMixer();
|
OssInitMixer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1429,7 +1523,7 @@ void AudioSetVolume(int volume)
|
|||||||
AlsaSetVolume(volume);
|
AlsaSetVolume(volume);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_OSS
|
#ifdef USE_OSS
|
||||||
#warning "AudioSetVolume not written"
|
OssSetVolume(volume);
|
||||||
#endif
|
#endif
|
||||||
(void)volume;
|
(void)volume;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user