mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
Use different alsa device for AC3/pass-through.
This commit is contained in:
parent
329dbc5f07
commit
970493fb23
@ -1,5 +1,10 @@
|
||||
User Morone
|
||||
Data: Sun Jan 22 16:43:23 CET 2012
|
||||
|
||||
Use different alsa devices for AC3/pass-through and pcm.
|
||||
|
||||
User johns
|
||||
Data:
|
||||
Data: Sun Jan 22 11:12:57 CET 2012
|
||||
|
||||
Add dummy player and control for suspend mode.
|
||||
Buffertime compile time configurable in ms.
|
||||
|
@ -79,6 +79,8 @@ Setup: environment
|
||||
only if alsa is configured
|
||||
ALSA_DEVICE=default
|
||||
alsa PCM device name
|
||||
ALSA_AC3_DEVICE=
|
||||
alsa AC3/pass-though device name
|
||||
ALSA_MIXER=default
|
||||
alsa control device name
|
||||
ALSA_MIXER_CHANNEL=PCM
|
||||
@ -128,6 +130,8 @@ Setup: /etc/vdr/setup.conf
|
||||
softhddevice.AudioPassthrough = 0
|
||||
0 = none, 1 = AC-3
|
||||
|
||||
for AC-3 the pass-through device is used.
|
||||
|
||||
softhddevice.AutoCrop.Interval = 0
|
||||
0 disables auto-crop
|
||||
n each 'n' frames auto-crop is checked.
|
||||
|
79
audio.c
79
audio.c
@ -112,7 +112,7 @@ typedef struct _audio_module_
|
||||
int (*FreeBytes) (void); ///< number of bytes free in buffer
|
||||
uint64_t(*GetDelay) (void); ///< get current audio delay
|
||||
void (*SetVolume) (int); ///< set output volume
|
||||
int (*Setup) (int *, int *); ///< setup channels, samplerate
|
||||
int (*Setup) (int *, int *, int); ///< setup channels, samplerate
|
||||
void (*Init) (void); ///< initialize audio output module
|
||||
void (*Exit) (void); ///< cleanup audio output module
|
||||
} AudioModule;
|
||||
@ -128,6 +128,7 @@ static const char *AudioModuleName; ///< which audio module to use
|
||||
/// Selected audio module.
|
||||
static const AudioModule *AudioUsedModule = &NoopModule;
|
||||
static const char *AudioPCMDevice; ///< alsa/OSS PCM device name
|
||||
static const char *AudioAC3Device; ///< alsa/OSS AC3 device name
|
||||
static const char *AudioMixerDevice; ///< alsa/OSS mixer device name
|
||||
static const char *AudioMixerChannel; ///< alsa/OSS mixer channel name
|
||||
static volatile char AudioRunning; ///< thread running / stopped
|
||||
@ -696,18 +697,24 @@ static void AlsaThreadFlushBuffers(void)
|
||||
|
||||
/**
|
||||
** Open alsa pcm device.
|
||||
**
|
||||
** @param use_ac3 use ac3/pass-through device
|
||||
*/
|
||||
static snd_pcm_t *AlsaOpenPCM(void)
|
||||
static snd_pcm_t *AlsaOpenPCM(int use_ac3)
|
||||
{
|
||||
const char *device;
|
||||
snd_pcm_t *handle;
|
||||
int err;
|
||||
|
||||
if (!(device = AudioPCMDevice)) {
|
||||
if (!(device = getenv("ALSA_DEVICE"))) {
|
||||
device = "default";
|
||||
}
|
||||
// &&|| hell
|
||||
if (!(use_ac3 && ((device = AudioAC3Device)
|
||||
|| (device = getenv("ALSA_PASSTHROUGH_DEVICE"))))
|
||||
&& !(device = AudioPCMDevice) && !(device = getenv("ALSA_DEVICE"))) {
|
||||
device = "default";
|
||||
}
|
||||
Debug(3, "audio/alsa: &&|| hell '%s'\n", device);
|
||||
|
||||
// open none blocking; if device is already used, we don't want wait
|
||||
if ((err =
|
||||
snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK,
|
||||
SND_PCM_NONBLOCK)) < 0) {
|
||||
@ -734,7 +741,7 @@ static void AlsaInitPCM(void)
|
||||
int err;
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
|
||||
if (!(handle = AlsaOpenPCM())) {
|
||||
if (!(handle = AlsaOpenPCM(0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -878,6 +885,7 @@ static uint64_t AlsaGetDelay(void)
|
||||
**
|
||||
** @param freq sample frequency
|
||||
** @param channels number of channels
|
||||
** @param use_ac3 use ac3/pass-through device
|
||||
**
|
||||
** @retval 0 everything ok
|
||||
** @retval 1 didn't support frequency/channels combination
|
||||
@ -885,7 +893,7 @@ static uint64_t AlsaGetDelay(void)
|
||||
**
|
||||
** @todo audio changes must be queued and done when the buffer is empty
|
||||
*/
|
||||
static int AlsaSetup(int *freq, int *channels)
|
||||
static int AlsaSetup(int *freq, int *channels, int use_ac3)
|
||||
{
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
snd_pcm_uframes_t period_size;
|
||||
@ -904,7 +912,7 @@ static int AlsaSetup(int *freq, int *channels)
|
||||
handle = AlsaPCMHandle;
|
||||
AlsaPCMHandle = NULL;
|
||||
snd_pcm_close(handle);
|
||||
if (!(handle = AlsaOpenPCM())) {
|
||||
if (!(handle = AlsaOpenPCM(use_ac3))) {
|
||||
return -1;
|
||||
}
|
||||
AlsaPCMHandle = handle;
|
||||
@ -1584,6 +1592,7 @@ static uint64_t OssGetDelay(void)
|
||||
**
|
||||
** @param freq sample frequency
|
||||
** @param channels number of channels
|
||||
** @param use_ac3 use ac3/pass-through device
|
||||
**
|
||||
** @retval 0 everything ok
|
||||
** @retval 1 didn't support frequency/channels combination
|
||||
@ -1591,7 +1600,8 @@ static uint64_t OssGetDelay(void)
|
||||
**
|
||||
** @todo audio changes must be queued and done when the buffer is empty
|
||||
*/
|
||||
static int OssSetup(int *freq, int *channels)
|
||||
static int OssSetup(int *freq, int *channels, __attribute__ ((unused))
|
||||
int use_ac3)
|
||||
{
|
||||
int ret;
|
||||
int tmp;
|
||||
@ -1690,6 +1700,8 @@ static int OssSetup(int *freq, int *channels)
|
||||
|
||||
/**
|
||||
** Initialize OSS audio output module.
|
||||
**
|
||||
** @param use_ac3 use ac3/pass-through device
|
||||
*/
|
||||
static void OssInit(void)
|
||||
{
|
||||
@ -1790,7 +1802,8 @@ static void NoopSetVolume( __attribute__ ((unused))
|
||||
*/
|
||||
static int NoopSetup( __attribute__ ((unused))
|
||||
int *channels, __attribute__ ((unused))
|
||||
int *freq)
|
||||
int *freq, __attribute__ ((unused))
|
||||
int use_ac3)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@ -2040,6 +2053,7 @@ void AudioSetVolume(int volume)
|
||||
**
|
||||
** @param freq sample frequency
|
||||
** @param channels number of channels
|
||||
** @param use_ac3 use ac3/pass-through device
|
||||
**
|
||||
** @retval 0 everything ok
|
||||
** @retval 1 didn't support frequency/channels combination
|
||||
@ -2047,9 +2061,10 @@ void AudioSetVolume(int volume)
|
||||
**
|
||||
** @todo audio changes must be queued and done when the buffer is empty
|
||||
*/
|
||||
int AudioSetup(int *freq, int *channels)
|
||||
int AudioSetup(int *freq, int *channels, int use_ac3)
|
||||
{
|
||||
Debug(3, "audio: channels %d frequency %d hz\n", *channels, *freq);
|
||||
Debug(3, "audio: channels %d frequency %d hz %s\n", *channels, *freq,
|
||||
use_ac3 ? "ac3" : "pcm");
|
||||
|
||||
// invalid parameter
|
||||
if (!freq || !channels || !*freq || !*channels) {
|
||||
@ -2059,9 +2074,9 @@ int AudioSetup(int *freq, int *channels)
|
||||
}
|
||||
#ifdef USE_AUDIORING
|
||||
// FIXME: need to store possible combination and report this
|
||||
return AudioRingAdd(*freq, *channels);
|
||||
return AudioRingAdd(*freq, *channels, use_ac3);
|
||||
#endif
|
||||
return AudioUsedModule->Setup(freq, channels);
|
||||
return AudioUsedModule->Setup(freq, channels, use_ac3);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2073,15 +2088,37 @@ int AudioSetup(int *freq, int *channels)
|
||||
*/
|
||||
void AudioSetDevice(const char *device)
|
||||
{
|
||||
AudioModuleName = "alsa"; // detect alsa/OSS
|
||||
if (!device[0]) {
|
||||
AudioModuleName = "noop";
|
||||
} else if (device[0] == '/') {
|
||||
AudioModuleName = "oss";
|
||||
if (!AudioModuleName) {
|
||||
AudioModuleName = "alsa"; // detect alsa/OSS
|
||||
if (!device[0]) {
|
||||
AudioModuleName = "noop";
|
||||
} else if (device[0] == '/') {
|
||||
AudioModuleName = "oss";
|
||||
}
|
||||
}
|
||||
AudioPCMDevice = device;
|
||||
}
|
||||
|
||||
/**
|
||||
** Set pass-through audio device.
|
||||
**
|
||||
** @param device name of pass-through device (fe. "hw:0,1")
|
||||
**
|
||||
** @note this is currently usable with alsa only.
|
||||
*/
|
||||
void AudioSetDeviceAC3(const char *device)
|
||||
{
|
||||
if (!AudioModuleName) {
|
||||
AudioModuleName = "alsa"; // detect alsa/OSS
|
||||
if (!device[0]) {
|
||||
AudioModuleName = "noop";
|
||||
} else if (device[0] == '/') {
|
||||
AudioModuleName = "oss";
|
||||
}
|
||||
}
|
||||
AudioAC3Device = device;
|
||||
}
|
||||
|
||||
/**
|
||||
** Initialize audio output module.
|
||||
**
|
||||
@ -2125,7 +2162,7 @@ void AudioInit(void)
|
||||
AudioUsedModule->Init();
|
||||
freq = 48000;
|
||||
chan = 2;
|
||||
if (AudioSetup(&freq, &chan)) { // set default parameters
|
||||
if (AudioSetup(&freq, &chan, 0)) { // set default parameters
|
||||
Error(_("audio: can't do initial setup\n"));
|
||||
}
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
|
3
audio.h
3
audio.h
@ -37,12 +37,13 @@ extern uint64_t AudioGetDelay(void); ///< get current audio delay
|
||||
extern void AudioSetClock(int64_t); ///< set audio clock base
|
||||
extern int64_t AudioGetClock(); ///< get current audio clock
|
||||
extern void AudioSetVolume(int); ///< set volume
|
||||
extern int AudioSetup(int *, int *); ///< setup audio output
|
||||
extern int AudioSetup(int *, int *, int); ///< setup audio output
|
||||
|
||||
//extern void AudioPlay(void); ///< play audio
|
||||
//extern void AudioPause(void); ///< pause audio
|
||||
|
||||
extern void AudioSetDevice(const char *); ///< set PCM audio device
|
||||
extern void AudioSetDeviceAC3(const char *); ///< set Passthrough device
|
||||
extern void AudioInit(void); ///< setup audio module
|
||||
extern void AudioExit(void); ///< cleanup and exit audio module
|
||||
|
||||
|
35
codec.c
35
codec.c
@ -320,20 +320,30 @@ static void Codec_draw_horiz_band(AVCodecContext * video_ctx,
|
||||
**
|
||||
** @param hw_decoder video hardware decoder
|
||||
**
|
||||
** @returns private decoder pointer for audio/video decoder.
|
||||
** @returns private decoder pointer for video decoder.
|
||||
*/
|
||||
VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder * hw_decoder)
|
||||
{
|
||||
VideoDecoder *decoder;
|
||||
|
||||
if (!(decoder = calloc(1, sizeof(*decoder)))) {
|
||||
Fatal(_("codec: Can't allocate vodeo decoder\n"));
|
||||
Fatal(_("codec: can't allocate vodeo decoder\n"));
|
||||
}
|
||||
decoder->HwDecoder = hw_decoder;
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
** Deallocate a video decoder context.
|
||||
**
|
||||
** @param decoder private video decoder
|
||||
*/
|
||||
void CodecVideoDelDecoder(VideoDecoder * decoder)
|
||||
{
|
||||
free(decoder);
|
||||
}
|
||||
|
||||
/**
|
||||
** Open video decoder.
|
||||
**
|
||||
@ -613,21 +623,29 @@ static char CodecPassthroughAC3; ///< pass ac3 through
|
||||
/**
|
||||
** Allocate a new audio decoder context.
|
||||
**
|
||||
** @param hw_decoder video hardware decoder
|
||||
**
|
||||
** @returns private decoder pointer for audio/video decoder.
|
||||
** @returns private decoder pointer for audio decoder.
|
||||
*/
|
||||
AudioDecoder *CodecAudioNewDecoder(void)
|
||||
{
|
||||
AudioDecoder *audio_decoder;
|
||||
|
||||
if (!(audio_decoder = calloc(1, sizeof(*audio_decoder)))) {
|
||||
Fatal(_("codec: Can't allocate audio decoder\n"));
|
||||
Fatal(_("codec: can't allocate audio decoder\n"));
|
||||
}
|
||||
|
||||
return audio_decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
** Deallocate an audio decoder context.
|
||||
**
|
||||
** @param decoder private audio decoder
|
||||
*/
|
||||
void CodecAudioDelDecoder(AudioDecoder * decoder)
|
||||
{
|
||||
free(decoder);
|
||||
}
|
||||
|
||||
/**
|
||||
** Open audio decoder.
|
||||
**
|
||||
@ -794,6 +812,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
if (audio_decoder->SampleRate != audio_ctx->sample_rate
|
||||
|| audio_decoder->Channels != audio_ctx->channels) {
|
||||
int err;
|
||||
int isAC3;
|
||||
|
||||
if (audio_decoder->ReSample) {
|
||||
audio_resample_close(audio_decoder->ReSample);
|
||||
@ -807,16 +826,18 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||
// SPDIF/HDMI passthrough
|
||||
if (CodecPassthroughAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
|
||||
audio_decoder->HwChannels = 2;
|
||||
isAC3 = 1;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
audio_decoder->HwChannels = audio_ctx->channels;
|
||||
isAC3 = 0;
|
||||
}
|
||||
|
||||
// channels not support?
|
||||
if ((err =
|
||||
AudioSetup(&audio_decoder->HwSampleRate,
|
||||
&audio_decoder->HwChannels))) {
|
||||
&audio_decoder->HwChannels, isAC3))) {
|
||||
Debug(3, "codec/audio: resample %dHz *%d -> %dHz *%d\n",
|
||||
audio_ctx->sample_rate, audio_ctx->channels,
|
||||
audio_decoder->HwSampleRate,
|
||||
|
10
softhddev.c
10
softhddev.c
@ -989,6 +989,7 @@ static char ConfigStartX11Server; ///< flag start the x11 server
|
||||
const char *CommandLineHelp(void)
|
||||
{
|
||||
return " -a device\taudio device (fe. alsa: hw:0,0 oss: /dev/dsp)\n"
|
||||
" -p device\taudio device (alsa only) for pass-through (hw:0,1)\n"
|
||||
" -d display\tdisplay of x11 server (fe. :0.0)\n"
|
||||
" -f\t\tstart with fullscreen window (only with window manager)\n"
|
||||
" -g geometry\tx11 window geometry wxh+x+y\n"
|
||||
@ -1007,10 +1008,13 @@ int ProcessArgs(int argc, char *const argv[])
|
||||
// Parse arguments.
|
||||
//
|
||||
for (;;) {
|
||||
switch (getopt(argc, argv, "-a:d:fg:x")) {
|
||||
switch (getopt(argc, argv, "-a:p:d:fg:x")) {
|
||||
case 'a': // audio device
|
||||
AudioSetDevice(optarg);
|
||||
continue;
|
||||
case 'p': // pass-through audio device
|
||||
AudioSetDeviceAC3(optarg);
|
||||
continue;
|
||||
case 'd': // x11 display name
|
||||
X11DisplayName = optarg;
|
||||
continue;
|
||||
@ -1154,12 +1158,12 @@ void SoftHdDeviceExit(void)
|
||||
|
||||
if (MyVideoDecoder) {
|
||||
CodecVideoClose(MyVideoDecoder);
|
||||
// FIXME: CodecDelVideoDecoder(MyVideoDecoder);
|
||||
CodecVideoDelDecoder(MyVideoDecoder);
|
||||
MyVideoDecoder = NULL;
|
||||
}
|
||||
if (MyAudioDecoder) {
|
||||
CodecAudioClose(MyAudioDecoder);
|
||||
// FIXME: CodecDelAudioDecoder(MyAudioDecoder);
|
||||
CodecAudioDelDecoder(MyAudioDecoder);
|
||||
MyAudioDecoder = NULL;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user