mirror of
				https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
				synced 2023-10-10 17:16:51 +00:00 
			
		
		
		
	Add Workaround for alsa blocking audio device.
This commit is contained in:
		@@ -1,3 +1,9 @@
 | 
			
		||||
User johns
 | 
			
		||||
Date:
 | 
			
		||||
 | 
			
		||||
    Add Workaround for alsa blocking audio device.
 | 
			
		||||
    Improves thread handling for audio flush and close.
 | 
			
		||||
 | 
			
		||||
User mini73
 | 
			
		||||
Date: Fri Jan 24 11:30:49 CET 2014
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								audio.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								audio.c
									
									
									
									
									
								
							@@ -123,6 +123,8 @@ static const AudioModule NoopModule;	///< forward definition of noop module
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
char AudioAlsaDriverBroken;		///< disable broken driver message
 | 
			
		||||
char AudioAlsaNoCloseOpen;		///< disable alsa close/open fix
 | 
			
		||||
char AudioAlsaCloseOpenDelay;		///< enable alsa close/open delay fix
 | 
			
		||||
 | 
			
		||||
static const char *AudioModuleName;	///< which audio module to use
 | 
			
		||||
 | 
			
		||||
@@ -1189,13 +1191,17 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
 | 
			
		||||
	// FIXME: if open fails for fe. pass-through, we never recover
 | 
			
		||||
	return -1;
 | 
			
		||||
    }
 | 
			
		||||
    if (1) {				// close+open to fix HDMI no sound bug
 | 
			
		||||
    if (!AudioAlsaNoCloseOpen) {	// close+open to fix HDMI no sound bug
 | 
			
		||||
	snd_pcm_t *handle;
 | 
			
		||||
 | 
			
		||||
	handle = AlsaPCMHandle;
 | 
			
		||||
	// FIXME: need lock
 | 
			
		||||
	AlsaPCMHandle = NULL;		// other threads should check handle
 | 
			
		||||
	snd_pcm_close(handle);
 | 
			
		||||
	if (AudioAlsaCloseOpenDelay) {
 | 
			
		||||
	    usleep(50 * 1000);		// 50ms delay for alsa recovery
 | 
			
		||||
	}
 | 
			
		||||
	// FIXME: can use multiple retries
 | 
			
		||||
	if (!(handle = AlsaOpenPCM(passthrough))) {
 | 
			
		||||
	    return -1;
 | 
			
		||||
	}
 | 
			
		||||
@@ -2043,25 +2049,27 @@ static void *AudioPlayHandlerThread(void *dummy)
 | 
			
		||||
	    int read;
 | 
			
		||||
	    int flush;
 | 
			
		||||
	    int err;
 | 
			
		||||
	    int i;
 | 
			
		||||
 | 
			
		||||
	    // look if there is a flush command in the queue
 | 
			
		||||
	    flush = 0;
 | 
			
		||||
	    filled = atomic_read(&AudioRingFilled);
 | 
			
		||||
	    read = AudioRingRead;
 | 
			
		||||
	    while (filled--) {
 | 
			
		||||
	    i = filled;
 | 
			
		||||
	    while (i--) {
 | 
			
		||||
		read = (read + 1) % AUDIO_RING_MAX;
 | 
			
		||||
		if (AudioRing[read].FlushBuffers) {
 | 
			
		||||
		    AudioRing[read].FlushBuffers = 0;
 | 
			
		||||
		    AudioRingRead = read;
 | 
			
		||||
		    atomic_set(&AudioRingFilled, filled);
 | 
			
		||||
		    // handle all flush in queue
 | 
			
		||||
		    flush = 1;
 | 
			
		||||
		    flush = filled - i;
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    if (flush) {
 | 
			
		||||
		Debug(3, "audio: flush\n");
 | 
			
		||||
		Debug(3, "audio: flush %d ring buffer(s)\n", flush);
 | 
			
		||||
		AudioUsedModule->FlushBuffers();
 | 
			
		||||
		atomic_sub(flush, &AudioRingFilled);
 | 
			
		||||
		if (AudioNextRing()) {
 | 
			
		||||
		    Debug(3, "audio: break after flush\n");
 | 
			
		||||
		    break;
 | 
			
		||||
@@ -2421,8 +2429,23 @@ void AudioFlushBuffers(void)
 | 
			
		||||
    int old;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if (atomic_read(&AudioRingFilled) >= AUDIO_RING_MAX) {
 | 
			
		||||
	// wait for space in ring buffer, should never happen
 | 
			
		||||
	for (i = 0; i < 24 * 2; ++i) {
 | 
			
		||||
	    if (atomic_read(&AudioRingFilled) < AUDIO_RING_MAX) {
 | 
			
		||||
		break;
 | 
			
		||||
	    }
 | 
			
		||||
	    Debug(3, "audio: flush out of ring buffers\n");
 | 
			
		||||
	    usleep(1 * 1000);		// avoid hot polling
 | 
			
		||||
	}
 | 
			
		||||
	if (atomic_read(&AudioRingFilled) >= AUDIO_RING_MAX) {
 | 
			
		||||
	    // FIXME: We can set the flush flag in the last wrote ring buffer
 | 
			
		||||
	    Error(_("audio: flush out of ring buffers\n"));
 | 
			
		||||
	    return;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    old = AudioRingWrite;
 | 
			
		||||
    // FIXME: check ring buffer overflow
 | 
			
		||||
    AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
 | 
			
		||||
    AudioRing[AudioRingWrite].FlushBuffers = 1;
 | 
			
		||||
    AudioRing[AudioRingWrite].Passthrough = AudioRing[old].Passthrough;
 | 
			
		||||
@@ -2439,12 +2462,13 @@ void AudioFlushBuffers(void)
 | 
			
		||||
 | 
			
		||||
    atomic_inc(&AudioRingFilled);
 | 
			
		||||
 | 
			
		||||
    // FIXME: wait for flush complete?
 | 
			
		||||
    // FIXME: wait for flush complete needed?
 | 
			
		||||
    for (i = 0; i < 24 * 2; ++i) {
 | 
			
		||||
	if (!AudioRunning) {		// wakeup thread to flush buffers
 | 
			
		||||
	    AudioRunning = 1;
 | 
			
		||||
	    pthread_cond_signal(&AudioStartCond);
 | 
			
		||||
	}
 | 
			
		||||
	// FIXME: waiting on zero isn't correct, but currently works
 | 
			
		||||
	if (!atomic_read(&AudioRingFilled)) {
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								audio.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								audio.h
									
									
									
									
									
								
							@@ -60,5 +60,7 @@ extern void AudioExit(void);		///< cleanup and exit audio module
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
extern char AudioAlsaDriverBroken;	///< disable broken driver message
 | 
			
		||||
extern char AudioAlsaNoCloseOpen;	///< disable alsa close/open fix
 | 
			
		||||
extern char AudioAlsaCloseOpenDelay;	///< enable alsa close/open delay fix
 | 
			
		||||
 | 
			
		||||
/// @}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: VDR \n"
 | 
			
		||||
"Report-Msgid-Bugs-To: <see README>\n"
 | 
			
		||||
"POT-Creation-Date: 2013-10-06 22:20+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2013-12-05 12:15+0100\n"
 | 
			
		||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
			
		||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
			
		||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
			
		||||
@@ -239,6 +239,9 @@ msgstr ""
 | 
			
		||||
msgid "audio: can't place %d samples in ring buffer\n"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "audio: flush out of ring buffers\n"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "audio: '%s' output module used\n"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 
 | 
			
		||||
@@ -2888,6 +2888,8 @@ const char *CommandLineHelp(void)
 | 
			
		||||
	"\tstill-hw-decoder\tenable hardware decoder for still-pictures\n"
 | 
			
		||||
	"\tstill-h264-hw-decoder\tenable h264 hw decoder for still-pictures\n"
 | 
			
		||||
	"\talsa-driver-broken\tdisable broken alsa driver message\n"
 | 
			
		||||
	"-talsa-no-close-open\tdisable close open to fix alsa no sound bug\n"
 | 
			
		||||
	"-talsa-close-open-delay\tenable close open delay to fix no sound bug\n"
 | 
			
		||||
	"\tignore-repeat-pict\tdisable repeat pict message\n"
 | 
			
		||||
	"  -D\t\tstart in detached mode\n";
 | 
			
		||||
}
 | 
			
		||||
@@ -2964,6 +2966,10 @@ int ProcessArgs(int argc, char *const argv[])
 | 
			
		||||
		    ConfigStillDecoder = 1;
 | 
			
		||||
		} else if (!strcasecmp("alsa-driver-broken", optarg)) {
 | 
			
		||||
		    AudioAlsaDriverBroken = 1;
 | 
			
		||||
		} else if (!strcasecmp("alsa-no-close-open", optarg)) {
 | 
			
		||||
		    AudioAlsaNoCloseOpen = 1;
 | 
			
		||||
		} else if (!strcasecmp("alsa-close-open-delay", optarg)) {
 | 
			
		||||
		    AudioAlsaCloseOpenDelay = 1;
 | 
			
		||||
		} else if (!strcasecmp("ignore-repeat-pict", optarg)) {
 | 
			
		||||
		    VideoIgnoreRepeatPict = 1;
 | 
			
		||||
		} else {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user