diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | README.txt | 4 | ||||
-rw-r--r-- | audio.c | 79 | ||||
-rw-r--r-- | audio.h | 3 | ||||
-rw-r--r-- | codec.c | 35 | ||||
-rw-r--r-- | softhddev.c | 10 |
6 files changed, 105 insertions, 33 deletions
@@ -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. @@ -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,16 +2088,38 @@ 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. ** ** @todo FIXME: make audio output module selectable. @@ -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 @@ -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 @@ -320,14 +320,14 @@ 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; @@ -335,6 +335,16 @@ VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder * hw_decoder) } /** +** Deallocate a video decoder context. +** +** @param decoder private video decoder +*/ +void CodecVideoDelDecoder(VideoDecoder * decoder) +{ + free(decoder); +} + +/** ** Open video decoder. ** ** @param decoder private video decoder @@ -613,22 +623,30 @@ 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. ** ** @param audio_decoder private 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, diff --git a/softhddev.c b/softhddev.c index 80abe9a..b1e29cf 100644 --- a/softhddev.c +++ b/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; } |