[MPlayer-dev-eng] [PATCH] Fix ao_dsound looping tail audio when shorter than video

David Bolen db3l.net at gmail.com
Fri Mar 6 22:49:35 CET 2009


After poking at ao_win32, I figured I'd take a peek at ao_dsound in
regards to my earlier issues with it - at the time I hadn't yet
started doing my own builds of mplayer.  The problem is that if you
have a file where the audio track is shorter than the video, the tail
end of the audio is repeated while the video completes.  There's some
other issues too, but that was the key one that prevented my use of
ao_dsound.

The attached proposed patch corrects this.  The basic flaw appears to
be that ao_dsound sets up the play buffer in looping mode.  I don't
understand why (it's not a requirement for a secondary DirectSound
buffer), but since I definitely get some audio glitches if it isn't
set, for the moment I'm willing to go with "because it works" as the
reason it was done this way originally.

Of course, if the audio runs out, Windows then obeys the loop request
so you get the repeated audio.  At least once when the normal audio
stream runs out (not sure if more, my sample media doesn't last long
enough), but then again during uninit() when the play call intended to
reset the looping flag actually restarts a buffers worth of audio.

The patch just clears the looping flag earlier if the final audio
chunk is seen, and protects against calling Play again unnecessarily
in uninit, if looping is already clear.

There's still an annoying sort of 1s granularity to ao_dsound (all
audio plays at least 1s, even if most of that is silence, and a
slightly more than 1s clip is almost always truncated to 1s) which I
think is due to the 1s buffer size and maybe not handling partial
buffers, but that's less intrusive than the audio repeats.

-- David

Index: ao_dsound.c
===================================================================
--- ao_dsound.c	(revision 28810)
+++ ao_dsound.c	(working copy)
@@ -562,7 +562,10 @@
 	if(immed)reset();
 	else{
 		DWORD status;
-		IDirectSoundBuffer_Play(hdsbuf, 0, 0, 0);
+                if (!IDirectSoundBuffer_GetStatus(hdsbuf,&status) && (status & DSBSTATUS_LOOPING)) {
+                    // Disable looping so we eventually terminate
+                    IDirectSoundBuffer_Play(hdsbuf, 0, 0, 0);
+                }
 		while(!IDirectSoundBuffer_GetStatus(hdsbuf,&status) && (status&DSBSTATUS_PLAYING))
 			usec_sleep(20000);
 	}
@@ -610,7 +613,14 @@
 
 	if (!(flags & AOPLAY_FINAL_CHUNK))
 	len = (len / ao_data.outburst) * ao_data.outburst;
-	return write_buffer(data, len);
+	len = write_buffer(data, len);
+
+        if (flags & AOPLAY_FINAL_CHUNK) {
+            // Disable looping to prevent repeating current buffer if video continues
+            IDirectSoundBuffer_Play(hdsbuf, 0, 0, 0);
+        }
+
+        return len;
 }
 
 /**




More information about the MPlayer-dev-eng mailing list