mirror of
https://github.com/jojo61/vdr-plugin-softhdcuvid.git
synced 2023-10-10 13:37:41 +02:00
- Remove OSS support from source, it is deprecated since kernel 2.6 (released December 2003)
- remove libavresample from source, deprecated since 2017 - make ALSA and libswresample mandatory for now
This commit is contained in:
parent
43135c43bc
commit
cf1a661c7b
61
Makefile
61
Makefile
@ -54,7 +54,7 @@ endif
|
||||
|
||||
ifeq ($(CUVID),1)
|
||||
ifeq ($(DRM),1)
|
||||
$(error Missmatch in Plugin selection)
|
||||
$(error Mismatch in Plugin selection)
|
||||
exit 1;
|
||||
endif
|
||||
endif
|
||||
@ -62,7 +62,7 @@ endif
|
||||
|
||||
ifeq ($(CUVID),1)
|
||||
ifeq ($(VAAPI),1)
|
||||
$(error Missmatch in Plugin selection)
|
||||
$(error Mismatch in Plugin selection)
|
||||
exit 1;
|
||||
endif
|
||||
endif
|
||||
@ -78,26 +78,11 @@ PLUGIN = softhdcuvid
|
||||
# support OPENGLOSD always needed
|
||||
OPENGLOSD=1
|
||||
|
||||
# support alsa audio output module
|
||||
ALSA ?= $(shell pkg-config --exists alsa && echo 1)
|
||||
# support OSS audio output module
|
||||
OSS ?= 1
|
||||
|
||||
# use DMPS
|
||||
SCREENSAVER=1
|
||||
|
||||
OPENGL=1
|
||||
|
||||
# use ffmpeg libswresample
|
||||
SWRESAMPLE ?= $(shell pkg-config --exists libswresample && echo 1)
|
||||
SWRESAMPLE = 1
|
||||
|
||||
# use libav libavresample
|
||||
#ifneq ($(SWRESAMPLE),1)
|
||||
#AVRESAMPLE ?= $(shell pkg-config --exists libavresample && echo 1#)
|
||||
#AVRESAMPLE = 1
|
||||
#endif
|
||||
|
||||
CONFIG += -DHAVE_GL # needed for mpv libs
|
||||
#CONFIG += -DSTILL_DEBUG=2 # still picture debug verbose level
|
||||
CONFIG += -DAV_INFO -DAV_INFO_TIME=3000 # info/debug a/v sync
|
||||
@ -149,16 +134,6 @@ APIVERSION = $(call PKGCFG,apiversion)
|
||||
|
||||
### Parse softhddevice config
|
||||
|
||||
ifeq ($(ALSA),1)
|
||||
CONFIG += -DUSE_ALSA
|
||||
_CFLAGS += $(shell pkg-config --cflags alsa)
|
||||
LIBS += $(shell pkg-config --libs alsa)
|
||||
endif
|
||||
|
||||
ifeq ($(OSS),1)
|
||||
CONFIG += -DUSE_OSS
|
||||
endif
|
||||
|
||||
ifeq ($(OPENGL),1)
|
||||
#_CFLAGS += $(shell pkg-config --cflags libva-glx)
|
||||
#LIBS += $(shell pkg-config --libs libva-glx)
|
||||
@ -226,11 +201,13 @@ SOFILE = libvdr-$(PLUGIN).so
|
||||
#
|
||||
# Test that libswresample is available
|
||||
#
|
||||
#ifneq (exists, $(shell pkg-config libswresample && echo exists))
|
||||
# $(warning ******************************************************************)
|
||||
# $(warning 'libswresample' not found!)
|
||||
# $(error ******************************************************************)
|
||||
#endif
|
||||
ifneq (exists, $(shell pkg-config libswresample && echo exists))
|
||||
$(warning ******************************************************************)
|
||||
$(warning 'libswresample' not found!)
|
||||
$(error ******************************************************************)
|
||||
endif
|
||||
_CFLAGS += $(shell pkg-config --cflags libswresample)
|
||||
LIBS += $(shell pkg-config --libs libswresample)
|
||||
|
||||
#
|
||||
# Test and set config for libavutil
|
||||
@ -265,22 +242,22 @@ endif
|
||||
_CFLAGS += $(shell pkg-config --cflags libavcodec)
|
||||
LIBS += $(shell pkg-config --libs libavcodec libavfilter)
|
||||
|
||||
#
|
||||
# Test and set config for alsa
|
||||
#
|
||||
ifneq (exists, $(shell pkg-config alsa && echo exists))
|
||||
$(warning ******************************************************************)
|
||||
$(warning 'alsa' not found!)
|
||||
$(error ******************************************************************)
|
||||
endif
|
||||
_CFLAGS += $(shell pkg-config --cflags alsa)
|
||||
LIBS += $(shell pkg-config --libs alsa)
|
||||
|
||||
ifeq ($(SCREENSAVER),1)
|
||||
CONFIG += -DUSE_SCREENSAVER
|
||||
_CFLAGS += $(shell pkg-config --cflags xcb-screensaver xcb-dpms)
|
||||
LIBS += $(shell pkg-config --libs xcb-screensaver xcb-dpms)
|
||||
endif
|
||||
ifeq ($(SWRESAMPLE),1)
|
||||
CONFIG += -DUSE_SWRESAMPLE
|
||||
_CFLAGS += $(shell pkg-config --cflags libswresample)
|
||||
LIBS += $(shell pkg-config --libs libswresample)
|
||||
endif
|
||||
ifeq ($(AVRESAMPLE),1)
|
||||
CONFIG += -DUSE_AVRESAMPLE
|
||||
_CFLAGS += $(shell pkg-config --cflags libavresample)
|
||||
LIBS += $(shell pkg-config --libs libavresample)
|
||||
endif
|
||||
|
||||
#_CFLAGS += $(shell pkg-config --cflags libavcodec x11 x11-xcb xcb xcb-icccm)
|
||||
#LIBS += -lrt $(shell pkg-config --libs libavcodec x11 x11-xcb xcb xcb-icccm)
|
||||
|
39
README.md
39
README.md
@ -25,14 +25,13 @@ A software and GPU emulated UHD output device plugin for VDR.
|
||||
|
||||
o Video decoder CUVID or VAAPI
|
||||
o Video output opengl or DRM
|
||||
o Audio FFMpeg / Alsa / Analog
|
||||
o Audio FFMpeg / Alsa / Digital
|
||||
o Audio FFMpeg / OSS / Analog
|
||||
o Audio FFMpeg / ALSA / Analog
|
||||
o Audio FFMpeg / ALSA / Digital
|
||||
o HDMI/SPDIF pass-through
|
||||
o Software volume, compression, normalize and channel resample
|
||||
o VDR ScaleVideo API
|
||||
o CUDA deinterlacer
|
||||
o Suspend / Dettach
|
||||
o Suspend / Detach
|
||||
o Support for ambilight
|
||||
o Support for Screencopy
|
||||
o PIP (Picture-in-Picture) (only for CUVID)
|
||||
@ -96,9 +95,6 @@ Install:
|
||||
make
|
||||
make install
|
||||
|
||||
You can edit Makefile to enable/disable Alsa / OSS
|
||||
support. The default is to autodetect as much as possible.
|
||||
|
||||
You have to start vdr with -P 'softhdcuvid -d :0.0 ..<more option>.. '
|
||||
|
||||
Beginners Guide for libplacebo:
|
||||
@ -148,27 +144,17 @@ Setup: environment
|
||||
Following is supported:
|
||||
|
||||
DISPLAY=:0.0
|
||||
x11 display name
|
||||
X11 display name
|
||||
|
||||
only if alsa is configured
|
||||
ALSA configuration:
|
||||
ALSA_DEVICE=default
|
||||
alsa PCM device name
|
||||
ALSA PCM device name
|
||||
ALSA_PASSTHROUGH_DEVICE=
|
||||
alsa pass-though (AC-3,E-AC-3,DTS,...) device name
|
||||
ALSA pass-though (AC-3,E-AC-3,DTS,...) device name
|
||||
ALSA_MIXER=default
|
||||
alsa control device name
|
||||
ALSA control device name
|
||||
ALSA_MIXER_CHANNEL=PCM
|
||||
alsa control channel name
|
||||
|
||||
only if oss is configured
|
||||
OSS_AUDIODEV=/dev/dsp
|
||||
oss dsp device name
|
||||
OSS_PASSTHROUGHDEV=
|
||||
oss pass-though (AC-3,E-AC-3,DTS,...) device name
|
||||
OSS_MIXERDEV=/dev/mixer
|
||||
oss mixer device name
|
||||
OSS_MIXER_CHANNEL=pcm
|
||||
oss mixer channel name
|
||||
ALSA control channel name
|
||||
|
||||
Setup: /etc/vdr/setup.conf
|
||||
------
|
||||
@ -197,7 +183,7 @@ Setup: /etc/vdr/setup.conf
|
||||
(only 0, 1, 4 supported with VA-API)
|
||||
|
||||
softhddevice.<res>.SkipChromaDeinterlace = 0
|
||||
0 = disabled, 1 = enabled (for slower cards, poor qualität)
|
||||
0 = disabled, 1 = enabled (for slower cards, poor qualit<EFBFBD>t)
|
||||
|
||||
softhddevice.<res>.InverseTelecine = 0
|
||||
0 = disabled, 1 = enabled
|
||||
@ -336,10 +322,7 @@ Commandline:
|
||||
|
||||
Selects audio output module and device.
|
||||
"" to disable audio output
|
||||
/... to use oss audio module (if compiled with oss
|
||||
support)
|
||||
other to use alsa audio module (if compiled with alsa
|
||||
support)
|
||||
other to use ALSA audio module
|
||||
|
||||
SVDRP:
|
||||
------
|
||||
|
520
audio.c
520
audio.c
@ -30,17 +30,12 @@
|
||||
///
|
||||
/// @note alsa async playback is broken, don't use it!
|
||||
///
|
||||
/// OSS PCM/Mixer api is supported.
|
||||
/// @see http://manuals.opensound.com/developer/
|
||||
///
|
||||
///
|
||||
/// @todo FIXME: there can be problems with little/big endian.
|
||||
///
|
||||
#ifdef DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
//#define USE_ALSA ///< enable alsa support
|
||||
//#define USE_OSS ///< enable OSS support
|
||||
#define USE_AUDIO_THREAD ///< use thread for audio playback
|
||||
#define USE_AUDIO_MIXER ///< use audio module mixer
|
||||
|
||||
@ -57,41 +52,12 @@
|
||||
#define _(str) gettext(str) ///< gettext shortcut
|
||||
#define _N(str) str ///< gettext_noop shortcut
|
||||
|
||||
#ifdef USE_ALSA
|
||||
#include <alsa/asoundlib.h>
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
// SNDCTL_DSP_HALT_OUTPUT compatibility
|
||||
#ifndef SNDCTL_DSP_HALT_OUTPUT
|
||||
#if defined(SNDCTL_DSP_RESET_OUTPUT)
|
||||
#define SNDCTL_DSP_HALT_OUTPUT SNDCTL_DSP_RESET_OUTPUT
|
||||
#elif defined(SNDCTL_DSP_RESET)
|
||||
#define SNDCTL_DSP_HALT_OUTPUT SNDCTL_DSP_RESET
|
||||
#else
|
||||
#error "No valid SNDCTL_DSP_HALT_OUTPUT found."
|
||||
#endif
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/syscall.h>
|
||||
#ifndef HAVE_PTHREAD_NAME
|
||||
/// only available with newer glibc
|
||||
#define pthread_setname_np(thread, name)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "iatomic.h" // portable atomic_t
|
||||
@ -723,8 +689,6 @@ static void AudioRingExit(void) {
|
||||
AudioRingWrite = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_ALSA
|
||||
|
||||
//============================================================================
|
||||
// A L S A
|
||||
//============================================================================
|
||||
@ -1358,480 +1322,6 @@ static const AudioModule AlsaModule = {
|
||||
.Exit = AlsaExit,
|
||||
};
|
||||
|
||||
#endif // USE_ALSA
|
||||
|
||||
#ifdef USE_OSS
|
||||
|
||||
//============================================================================
|
||||
// O S S
|
||||
//============================================================================
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// OSS variables
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static int OssPcmFildes = -1; ///< pcm file descriptor
|
||||
static int OssMixerFildes = -1; ///< mixer file descriptor
|
||||
static int OssMixerChannel; ///< mixer channel index
|
||||
static int OssFragmentTime; ///< fragment time in ms
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// OSS pcm
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Play samples from ringbuffer.
|
||||
**
|
||||
** @retval 0 ok
|
||||
** @retval 1 ring buffer empty
|
||||
** @retval -1 underrun error
|
||||
*/
|
||||
static int OssPlayRingbuffer(void) {
|
||||
int first;
|
||||
|
||||
first = 1;
|
||||
for (;;) {
|
||||
audio_buf_info bi;
|
||||
const void *p;
|
||||
int n;
|
||||
|
||||
if (ioctl(OssPcmFildes, SNDCTL_DSP_GETOSPACE, &bi) == -1) {
|
||||
Error(_("audio/oss: ioctl(SNDCTL_DSP_GETOSPACE): %s\n"), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
Debug(4, "audio/oss: %d bytes free\n", bi.bytes);
|
||||
|
||||
n = RingBufferGetReadPointer(AudioRing[AudioRingRead].RingBuffer, &p);
|
||||
if (!n) { // ring buffer empty
|
||||
if (first) { // only error on first loop
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (n < bi.bytes) { // not enough bytes in ring buffer
|
||||
bi.bytes = n;
|
||||
}
|
||||
if (bi.bytes <= 0) { // full or buffer empty
|
||||
break; // bi.bytes could become negative!
|
||||
}
|
||||
|
||||
if (AudioSoftVolume && !AudioRing[AudioRingRead].Passthrough) {
|
||||
// FIXME: quick&dirty cast
|
||||
AudioSoftAmplifier((int16_t *)p, bi.bytes);
|
||||
// FIXME: if not all are written, we double amplify them
|
||||
}
|
||||
for (;;) {
|
||||
n = write(OssPcmFildes, p, bi.bytes);
|
||||
if (n != bi.bytes) {
|
||||
if (n < 0) {
|
||||
if (n == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
Error(_("audio/oss: write error: %s\n"), strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
Warning(_("audio/oss: error not all bytes written\n"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
// advance how many could written
|
||||
RingBufferReadAdvance(AudioRing[AudioRingRead].RingBuffer, n);
|
||||
first = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Flush OSS buffers.
|
||||
*/
|
||||
static void OssFlushBuffers(void) {
|
||||
if (OssPcmFildes != -1) {
|
||||
// flush kernel buffers
|
||||
if (ioctl(OssPcmFildes, SNDCTL_DSP_HALT_OUTPUT, NULL) < 0) {
|
||||
Error(_("audio/oss: ioctl(SNDCTL_DSP_HALT_OUTPUT): %s\n"), strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// thread playback
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** OSS thread
|
||||
**
|
||||
** @retval -1 error
|
||||
** @retval 0 underrun
|
||||
** @retval 1 running
|
||||
*/
|
||||
static int OssThread(void) {
|
||||
int err;
|
||||
|
||||
if (!OssPcmFildes) {
|
||||
usleep(OssFragmentTime * 1000);
|
||||
return -1;
|
||||
}
|
||||
for (;;) {
|
||||
struct pollfd fds[1];
|
||||
|
||||
if (AudioPaused) {
|
||||
return 1;
|
||||
}
|
||||
// wait for space in kernel buffers
|
||||
fds[0].fd = OssPcmFildes;
|
||||
fds[0].events = POLLOUT | POLLERR;
|
||||
// wait for space in kernel buffers
|
||||
err = poll(fds, 1, OssFragmentTime);
|
||||
if (err < 0) {
|
||||
if (err == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
Error(_("audio/oss: error poll %s\n"), strerror(errno));
|
||||
usleep(OssFragmentTime * 1000);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!err || AudioPaused) { // timeout or some commands
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((err = OssPlayRingbuffer())) { // empty / error
|
||||
if (err < 0) { // underrun error
|
||||
return -1;
|
||||
}
|
||||
sched_yield();
|
||||
usleep(OssFragmentTime * 1000); // let fill/empty the buffers
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Open OSS pcm device.
|
||||
**
|
||||
** @param passthrough use pass-through (AC-3, ...) device
|
||||
*/
|
||||
static int OssOpenPCM(int passthrough) {
|
||||
const char *device;
|
||||
int fildes;
|
||||
|
||||
// &&|| hell
|
||||
if (!(passthrough && ((device = AudioPassthroughDevice) || (device = getenv("OSS_PASSTHROUGHDEV")))) &&
|
||||
!(device = AudioPCMDevice) && !(device = getenv("OSS_AUDIODEV"))) {
|
||||
device = "/dev/dsp";
|
||||
}
|
||||
if (!AudioDoingInit) {
|
||||
Info(_("audio/oss: using %sdevice '%s'\n"), passthrough ? "pass-through " : "", device);
|
||||
}
|
||||
|
||||
if ((fildes = open(device, O_WRONLY)) < 0) {
|
||||
Error(_("audio/oss: can't open dsp device '%s': %s\n"), device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return fildes;
|
||||
}
|
||||
|
||||
/**
|
||||
** Initialize OSS pcm device.
|
||||
**
|
||||
** @see AudioPCMDevice
|
||||
*/
|
||||
static void OssInitPCM(void) {
|
||||
int fildes;
|
||||
|
||||
fildes = OssOpenPCM(0);
|
||||
|
||||
OssPcmFildes = fildes;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// OSS Mixer
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Set OSS mixer volume (0-1000)
|
||||
**
|
||||
** @param volume volume (0 .. 1000)
|
||||
*/
|
||||
static void OssSetVolume(int volume) {
|
||||
int v;
|
||||
|
||||
if (OssMixerFildes != -1) {
|
||||
v = (volume * 255) / 1000;
|
||||
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
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Get OSS audio delay in time stamps.
|
||||
**
|
||||
** @returns audio delay in time stamps.
|
||||
*/
|
||||
static int64_t OssGetDelay(void) {
|
||||
int delay;
|
||||
int64_t pts;
|
||||
|
||||
// setup failure
|
||||
if (OssPcmFildes == -1 || !AudioRing[AudioRingRead].HwSampleRate) {
|
||||
return 0L;
|
||||
}
|
||||
if (!AudioRunning) { // audio not running
|
||||
Error(_("audio/oss: should not happen\n"));
|
||||
return 0L;
|
||||
}
|
||||
// delay in bytes in kernel buffers
|
||||
delay = -1;
|
||||
if (ioctl(OssPcmFildes, SNDCTL_DSP_GETODELAY, &delay) == -1) {
|
||||
Error(_("audio/oss: ioctl(SNDCTL_DSP_GETODELAY): %s\n"), strerror(errno));
|
||||
return 0L;
|
||||
}
|
||||
if (delay < 0) {
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
pts = ((int64_t)delay * 90 * 1000) /
|
||||
(AudioRing[AudioRingRead].HwSampleRate * AudioRing[AudioRingRead].HwChannels * AudioBytesProSample);
|
||||
|
||||
return pts;
|
||||
}
|
||||
|
||||
/**
|
||||
** Setup OSS audio for requested format.
|
||||
**
|
||||
** @param sample_rate sample rate/frequency
|
||||
** @param channels number of channels
|
||||
** @param passthrough use pass-through (AC-3, ...) device
|
||||
**
|
||||
** @retval 0 everything ok
|
||||
** @retval 1 didn't support frequency/channels combination
|
||||
** @retval -1 something gone wrong
|
||||
*/
|
||||
static int OssSetup(int *sample_rate, int *channels, int passthrough) {
|
||||
int ret;
|
||||
int tmp;
|
||||
int delay;
|
||||
audio_buf_info bi;
|
||||
|
||||
if (OssPcmFildes == -1) { // OSS not ready
|
||||
// FIXME: if open fails for fe. pass-through, we never recover
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (1) { // close+open for pcm / AC-3
|
||||
int fildes;
|
||||
|
||||
fildes = OssPcmFildes;
|
||||
OssPcmFildes = -1;
|
||||
close(fildes);
|
||||
if (!(fildes = OssOpenPCM(passthrough))) {
|
||||
return -1;
|
||||
}
|
||||
OssPcmFildes = fildes;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
tmp = AFMT_S16_NE; // native 16 bits
|
||||
if (ioctl(OssPcmFildes, SNDCTL_DSP_SETFMT, &tmp) == -1) {
|
||||
Error(_("audio/oss: ioctl(SNDCTL_DSP_SETFMT): %s\n"), strerror(errno));
|
||||
// FIXME: stop player, set setup failed flag
|
||||
return -1;
|
||||
}
|
||||
if (tmp != AFMT_S16_NE) {
|
||||
Error(_("audio/oss: device doesn't support 16 bit sample format.\n"));
|
||||
// FIXME: stop player, set setup failed flag
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = *channels;
|
||||
if (ioctl(OssPcmFildes, SNDCTL_DSP_CHANNELS, &tmp) == -1) {
|
||||
Error(_("audio/oss: ioctl(SNDCTL_DSP_CHANNELS): %s\n"), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (tmp != *channels) {
|
||||
Warning(_("audio/oss: device doesn't support %d channels.\n"), *channels);
|
||||
*channels = tmp;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
tmp = *sample_rate;
|
||||
if (ioctl(OssPcmFildes, SNDCTL_DSP_SPEED, &tmp) == -1) {
|
||||
Error(_("audio/oss: ioctl(SNDCTL_DSP_SPEED): %s\n"), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (tmp != *sample_rate) {
|
||||
Warning(_("audio/oss: device doesn't support %dHz sample rate.\n"), *sample_rate);
|
||||
*sample_rate = tmp;
|
||||
ret = 1;
|
||||
}
|
||||
#ifdef SNDCTL_DSP_POLICY
|
||||
tmp = 3;
|
||||
if (ioctl(OssPcmFildes, SNDCTL_DSP_POLICY, &tmp) == -1) {
|
||||
Error(_("audio/oss: ioctl(SNDCTL_DSP_POLICY): %s\n"), strerror(errno));
|
||||
} else {
|
||||
Info("audio/oss: set policy to %d\n", tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ioctl(OssPcmFildes, SNDCTL_DSP_GETOSPACE, &bi) == -1) {
|
||||
Error(_("audio/oss: ioctl(SNDCTL_DSP_GETOSPACE): %s\n"), strerror(errno));
|
||||
bi.fragsize = 4096;
|
||||
bi.fragstotal = 16;
|
||||
} else {
|
||||
Debug(3, "audio/oss: %d bytes buffered\n", bi.bytes);
|
||||
}
|
||||
|
||||
OssFragmentTime = (bi.fragsize * 1000) / (*sample_rate * *channels * AudioBytesProSample);
|
||||
|
||||
Debug(3, "audio/oss: buffer size %d %dms, fragment size %d %dms\n", bi.fragsize * bi.fragstotal,
|
||||
(bi.fragsize * bi.fragstotal * 1000) / (*sample_rate * *channels * AudioBytesProSample), bi.fragsize,
|
||||
OssFragmentTime);
|
||||
|
||||
// start when enough bytes for initial write
|
||||
AudioStartThreshold = (bi.fragsize - 1) * bi.fragstotal;
|
||||
|
||||
// buffer time/delay in ms
|
||||
delay = AudioBufferTime + 300;
|
||||
if (VideoAudioDelay > 0) {
|
||||
delay += VideoAudioDelay / 90;
|
||||
}
|
||||
if (AudioStartThreshold < (*sample_rate * *channels * AudioBytesProSample * delay) / 1000U) {
|
||||
AudioStartThreshold = (*sample_rate * *channels * AudioBytesProSample * delay) / 1000U;
|
||||
}
|
||||
// no bigger, than 1/3 the buffer
|
||||
if (AudioStartThreshold > AudioRingBufferSize / 3) {
|
||||
AudioStartThreshold = AudioRingBufferSize / 3;
|
||||
}
|
||||
|
||||
if (!AudioDoingInit) {
|
||||
Info(_("audio/oss: delay %ums\n"),
|
||||
(AudioStartThreshold * 1000) / (*sample_rate * *channels * AudioBytesProSample));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
** Play audio.
|
||||
*/
|
||||
static void OssPlay(void) {}
|
||||
|
||||
/**
|
||||
** Pause audio.
|
||||
*/
|
||||
void OssPause(void) {}
|
||||
|
||||
/**
|
||||
** Initialize OSS audio output module.
|
||||
*/
|
||||
static void OssInit(void) {
|
||||
OssInitPCM();
|
||||
OssInitMixer();
|
||||
}
|
||||
|
||||
/**
|
||||
** Cleanup OSS audio output module.
|
||||
*/
|
||||
static void OssExit(void) {
|
||||
if (OssPcmFildes != -1) {
|
||||
close(OssPcmFildes);
|
||||
OssPcmFildes = -1;
|
||||
}
|
||||
if (OssMixerFildes != -1) {
|
||||
close(OssMixerFildes);
|
||||
OssMixerFildes = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** OSS module.
|
||||
*/
|
||||
static const AudioModule OssModule = {
|
||||
.Name = "oss",
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
.Thread = OssThread,
|
||||
#endif
|
||||
.FlushBuffers = OssFlushBuffers,
|
||||
.GetDelay = OssGetDelay,
|
||||
.SetVolume = OssSetVolume,
|
||||
.Setup = OssSetup,
|
||||
.Play = OssPlay,
|
||||
.Pause = OssPause,
|
||||
.Init = OssInit,
|
||||
.Exit = OssExit,
|
||||
};
|
||||
|
||||
#endif // USE_OSS
|
||||
|
||||
//============================================================================
|
||||
// Noop
|
||||
//============================================================================
|
||||
@ -2089,12 +1579,7 @@ static void AudioExitThread(void) {
|
||||
** Table of all audio modules.
|
||||
*/
|
||||
static const AudioModule *AudioModules[] = {
|
||||
#ifdef USE_ALSA
|
||||
&AlsaModule,
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
&OssModule,
|
||||
#endif
|
||||
&NoopModule,
|
||||
};
|
||||
|
||||
@ -2666,12 +2151,7 @@ void AudioInit(void) {
|
||||
int chan;
|
||||
|
||||
name = "noop";
|
||||
#ifdef USE_OSS
|
||||
name = "oss";
|
||||
#endif
|
||||
#ifdef USE_ALSA
|
||||
name = "alsa";
|
||||
#endif
|
||||
if (AudioModuleName) {
|
||||
name = AudioModuleName;
|
||||
}
|
||||
|
68
codec.c
68
codec.c
@ -36,10 +36,6 @@
|
||||
#define USE_AUDIO_DRIFT_CORRECTION
|
||||
/// compile AC-3 audio drift correction support (very experimental)
|
||||
#define USE_AC3_DRIFT_CORRECTION
|
||||
/// use ffmpeg libswresample API (autodected, Makefile)
|
||||
#define noUSE_SWRESAMPLE
|
||||
/// use libav libavresample API (autodected, Makefile)
|
||||
#define noUSE_AVRESAMPLE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -62,17 +58,8 @@
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavutil/opt.h>
|
||||
|
||||
#ifdef USE_SWRESAMPLE
|
||||
#include <libswresample/swresample.h>
|
||||
#endif
|
||||
#ifdef USE_AVRESAMPLE
|
||||
#include <libavresample/avresample.h>
|
||||
#include <libavutil/opt.h>
|
||||
#endif
|
||||
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
|
||||
// clang-format off
|
||||
@ -673,17 +660,7 @@ struct _audio_decoder_ {
|
||||
int HwChannels; ///< hw channels
|
||||
|
||||
AVFrame *Frame; ///< decoded audio frame buffer
|
||||
|
||||
#ifdef USE_SWRESAMPLE
|
||||
#if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 15, 100)
|
||||
struct SwrContext *Resample; ///< ffmpeg software resample context
|
||||
#else
|
||||
SwrContext *Resample; ///< ffmpeg software resample context
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USE_AVRESAMPLE
|
||||
AVAudioResampleContext *Resample; ///< libav software resample context
|
||||
#endif
|
||||
|
||||
uint16_t Spdif[24576 / 2]; ///< SPDIF output buffer
|
||||
int SpdifIndex; ///< index into SPDIF output buffer
|
||||
@ -810,16 +787,9 @@ void CodecAudioOpen(AudioDecoder *audio_decoder, int codec_id) {
|
||||
void CodecAudioClose(AudioDecoder *audio_decoder) {
|
||||
// FIXME: output any buffered data
|
||||
|
||||
#ifdef USE_SWRESAMPLE
|
||||
if (audio_decoder->Resample) {
|
||||
swr_free(&audio_decoder->Resample);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AVRESAMPLE
|
||||
if (audio_decoder->Resample) {
|
||||
avresample_free(&audio_decoder->Resample);
|
||||
}
|
||||
#endif
|
||||
if (audio_decoder->AudioCtx) {
|
||||
pthread_mutex_lock(&CodecLockMutex);
|
||||
avcodec_close(audio_decoder->AudioCtx);
|
||||
@ -1094,8 +1064,6 @@ static int CodecAudioPassthroughHelper(AudioDecoder *audio_decoder, const AVPack
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(USE_SWRESAMPLE) || defined(USE_AVRESAMPLE)
|
||||
|
||||
/**
|
||||
** Set/update audio pts clock.
|
||||
**
|
||||
@ -1175,7 +1143,6 @@ static void CodecAudioSetClock(AudioDecoder *audio_decoder, int64_t pts) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_SWRESAMPLE
|
||||
if (audio_decoder->Resample && audio_decoder->DriftCorr) {
|
||||
int distance;
|
||||
|
||||
@ -1189,17 +1156,6 @@ static void CodecAudioSetClock(AudioDecoder *audio_decoder, int64_t pts) {
|
||||
Debug(3, "codec/audio: swr_set_compensation failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AVRESAMPLE
|
||||
if (audio_decoder->Resample && audio_decoder->DriftCorr) {
|
||||
int distance;
|
||||
|
||||
distance = (pts_diff * audio_decoder->HwSampleRate) / (900 * 1000);
|
||||
if (avresample_set_compensation(audio_decoder->Resample, audio_decoder->DriftCorr / 10, distance)) {
|
||||
Debug(3, "codec/audio: swr_set_compensation failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (1) {
|
||||
static int c;
|
||||
|
||||
@ -1239,7 +1195,6 @@ static void CodecAudioUpdateFormat(AudioDecoder *audio_decoder) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SWRESAMPLE
|
||||
audio_decoder->Resample = swr_alloc_set_opts(audio_decoder->Resample, audio_ctx->channel_layout, AV_SAMPLE_FMT_S16,
|
||||
audio_decoder->HwSampleRate, audio_ctx->channel_layout,
|
||||
audio_ctx->sample_fmt, audio_ctx->sample_rate, 0, NULL);
|
||||
@ -1248,27 +1203,6 @@ static void CodecAudioUpdateFormat(AudioDecoder *audio_decoder) {
|
||||
} else {
|
||||
Error(_("codec/audio: can't setup resample\n"));
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AVRESAMPLE
|
||||
if (!(audio_decoder->Resample = avresample_alloc_context())) {
|
||||
Error(_("codec/audio: can't setup resample\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
av_opt_set_int(audio_decoder->Resample, "in_channel_layout", audio_ctx->channel_layout, 0);
|
||||
av_opt_set_int(audio_decoder->Resample, "in_sample_fmt", audio_ctx->sample_fmt, 0);
|
||||
av_opt_set_int(audio_decoder->Resample, "in_sample_rate", audio_ctx->sample_rate, 0);
|
||||
av_opt_set_int(audio_decoder->Resample, "out_channel_layout", audio_ctx->channel_layout, 0);
|
||||
av_opt_set_int(audio_decoder->Resample, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
||||
av_opt_set_int(audio_decoder->Resample, "out_sample_rate", audio_decoder->HwSampleRate, 0);
|
||||
|
||||
if (avresample_open(audio_decoder->Resample)) {
|
||||
avresample_free(&audio_decoder->Resample);
|
||||
audio_decoder->Resample = NULL;
|
||||
Error(_("codec/audio: can't open resample\n"));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1340,8 +1274,6 @@ void CodecAudioDecode(AudioDecoder *audio_decoder, const AVPacket *avpkt) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Flush the audio decoder.
|
||||
**
|
||||
|
90
po/de_DE.po
90
po/de_DE.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR \n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2021-12-27 13:13+0100\n"
|
||||
"POT-Creation-Date: 2021-12-30 10:23+0100\n"
|
||||
"PO-Revision-Date: blabla\n"
|
||||
"Last-Translator: blabla\n"
|
||||
"Language-Team: blabla\n"
|
||||
@ -140,91 +140,6 @@ msgstr ""
|
||||
msgid "snd_pcm_drop(): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: ioctl(SNDCTL_DSP_GETOSPACE): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: write error: %s\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "audio/oss: error not all bytes written\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: ioctl(SNDCTL_DSP_HALT_OUTPUT): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: error poll %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: using %sdevice '%s'\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: can't open dsp device '%s': %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: ioctl(MIXER_WRITE): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: can't open mixer device '%s': %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: ioctl(SOUND_MIXER_READ_DEVMASK): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: channel '%s' not supported\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: channel '%s' not found\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "audio/oss: should not happen\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: ioctl(SNDCTL_DSP_GETODELAY): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: ioctl(SNDCTL_DSP_SETFMT): %s\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "audio/oss: device doesn't support 16 bit sample format.\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: ioctl(SNDCTL_DSP_CHANNELS): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: device doesn't support %d channels.\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: ioctl(SNDCTL_DSP_SPEED): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: device doesn't support %dHz sample rate.\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: ioctl(SNDCTL_DSP_POLICY): %s\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio/oss: delay %ums\n"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "audio: can't set channels %d sample-rate %dHz\n"
|
||||
msgstr ""
|
||||
@ -306,9 +221,6 @@ msgstr ""
|
||||
msgid "codec/audio: can't setup resample\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "codec/audio: can't open resample\n"
|
||||
msgstr ""
|
||||
|
||||
msgid "A software and GPU emulated UHD device"
|
||||
msgstr ""
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user