Ken Thomases : winecoreaudio: Protect against AudioUnitRender clobbering our buffer list.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jul 13 08:30:35 CDT 2007


Module: wine
Branch: master
Commit: 41303fbd6a0283fa7451eda5809ebb9eff7e5856
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=41303fbd6a0283fa7451eda5809ebb9eff7e5856

Author: Ken Thomases <ken at codeweavers.com>
Date:   Fri Jul 13 07:21:36 2007 -0500

winecoreaudio: Protect against AudioUnitRender clobbering our buffer list.

---

 dlls/winecoreaudio.drv/audio.c |   26 +++++++++++++++++++++++++-
 1 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/dlls/winecoreaudio.drv/audio.c b/dlls/winecoreaudio.drv/audio.c
index 1c9c770..7f5f66a 100644
--- a/dlls/winecoreaudio.drv/audio.c
+++ b/dlls/winecoreaudio.drv/audio.c
@@ -189,6 +189,7 @@ typedef struct {
 
     AudioUnit       audioUnit;
     AudioBufferList*bufferList;
+    AudioBufferList*bufferListCopy;
 
     /* Record state of debug channels at open.  Used to control fprintf's since
      * we can't use Wine debug channel calls in non-Wine AudioUnit threads. */
@@ -1728,6 +1729,8 @@ static void widHelper_DestroyAudioBufferList(AudioBufferList* list)
 }
 
 
+#define AUDIOBUFFERLISTSIZE(numBuffers) (offsetof(AudioBufferList, mBuffers) + (numBuffers) * sizeof(AudioBuffer))
+
 /**************************************************************************
  *                    widHelper_AllocateAudioBufferList          [internal]
  * Convenience function to allocate our audio buffers
@@ -1756,7 +1759,7 @@ static AudioBufferList* widHelper_AllocateAudioBufferList(UInt32 numChannels, UI
     bytesPerFrame = bitsPerChannel * channelsPerFrame / 8;
     bytesPerBuffer = bytesPerFrame * bufferFrames;
 
-    list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, offsetof(AudioBufferList, mBuffers) + numBuffers * sizeof(AudioBuffer));
+    list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, AUDIOBUFFERLISTSIZE(numBuffers));
     if (list == NULL)
         return NULL;
 
@@ -1871,6 +1874,20 @@ static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
         return MMSYSERR_NOMEM;
     }
 
+    /* Keep a copy of the buffer list structure (but not the buffers themselves)
+     * in case AudioUnitRender clobbers the original, as it is wont to do. */
+    wwi->bufferListCopy = HeapAlloc(GetProcessHeap(), 0, AUDIOBUFFERLISTSIZE(wwi->bufferList->mNumberBuffers));
+    if (wwi->bufferListCopy == NULL)
+    {
+        ERR("Failed to allocate buffer list copy\n");
+        widHelper_DestroyAudioBufferList(wwi->bufferList);
+        AudioUnitUninitialize(wwi->audioUnit);
+        AudioUnit_CloseAudioUnit(wwi->audioUnit);
+        OSSpinLockUnlock(&wwi->lock);
+        return MMSYSERR_NOMEM;
+    }
+    memcpy(wwi->bufferListCopy, wwi->bufferList, AUDIOBUFFERLISTSIZE(wwi->bufferList->mNumberBuffers));
+
     OSSpinLockUnlock(&wwi->lock);
 
     return widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
@@ -1931,6 +1948,8 @@ static DWORD widClose(WORD wDevID)
         /* Dellocate our audio buffers */
         widHelper_DestroyAudioBufferList(wwi->bufferList);
         wwi->bufferList = NULL;
+        HeapFree(GetProcessHeap(), 0, wwi->bufferListCopy);
+        wwi->bufferListCopy = NULL;
 
         ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
     }
@@ -2350,6 +2369,11 @@ OSStatus CoreAudio_wiAudioUnitIOProc(void *inRefCon,
 
     OSSpinLockUnlock(&wwi->lock);
 
+    /* Restore the audio buffer list structure from backup, in case
+     * AudioUnitRender clobbered it.  (It modifies mDataByteSize and may even
+     * give us a different mData buffer to avoid a copy.) */
+    memcpy(wwi->bufferList, wwi->bufferListCopy, AUDIOBUFFERLISTSIZE(wwi->bufferList->mNumberBuffers));
+
     if (needNotify) wodSendNotifyInputCompletionsMessage(wwi);
     return err;
 }




More information about the wine-cvs mailing list