mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 564734 - Ensure all audio is queued before draining on win32. r=kinetik
This commit is contained in:
parent
48c6564be0
commit
8d537247f7
@ -29,3 +29,6 @@ bug526411_latency.patch: reduce requested latency to 250ms to match OGGPLAY_AUDI
|
||||
sydney_aix.patch: Bug 499266 - add support for AIX 5.x
|
||||
|
||||
bug562488_oss_destroy_crash.patch: Fix crash in OSS backend when destroying stream.
|
||||
|
||||
bug564734-win32-drain.patch: Ensure we can drain audio stream when there's less
|
||||
than one block's worth of data left to be written. Also ensure that data is played.
|
149
media/libsydneyaudio/bug564734-win32-drain.patch
Normal file
149
media/libsydneyaudio/bug564734-win32-drain.patch
Normal file
@ -0,0 +1,149 @@
|
||||
diff --git a/media/libsydneyaudio/src/sydney_audio_waveapi.c b/media/libsydneyaudio/src/sydney_audio_waveapi.c
|
||||
--- a/media/libsydneyaudio/src/sydney_audio_waveapi.c
|
||||
+++ b/media/libsydneyaudio/src/sydney_audio_waveapi.c
|
||||
@@ -121,16 +121,17 @@ struct sa_stream {
|
||||
};
|
||||
|
||||
|
||||
/** Forward definitions of audio api specific functions */
|
||||
int allocateBlocks(int size, int count, WAVEHDR** blocks);
|
||||
int freeBlocks(WAVEHDR* blocks);
|
||||
int openAudio(sa_stream_t *s);
|
||||
int closeAudio(sa_stream_t * s);
|
||||
+int writeBlock(sa_stream_t *s, WAVEHDR* current);
|
||||
int writeAudio(sa_stream_t *s, LPSTR data, int bytes);
|
||||
int getSAErrorCode(int waveErrorCode);
|
||||
|
||||
void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT uMsg,
|
||||
DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
|
||||
|
||||
/** Normal way to open a PCM device */
|
||||
int sa_stream_create_pcm(sa_stream_t **s,
|
||||
@@ -320,20 +321,32 @@ int sa_stream_pause(sa_stream_t *s) {
|
||||
|
||||
status = waveOutPause(s->hWaveOut);
|
||||
HANDLE_WAVE_ERROR(status, "resuming audio playback");
|
||||
|
||||
s->playing = 0;
|
||||
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
+
|
||||
/** Block until all audio has been played */
|
||||
int sa_stream_drain(sa_stream_t *s) {
|
||||
+ int status;
|
||||
+ WAVEHDR* current;
|
||||
+
|
||||
ERROR_IF_NO_INIT(s);
|
||||
-
|
||||
+
|
||||
+ current = &(s->waveBlocks[s->waveCurrentBlock]);
|
||||
+ if (current->dwUser) {
|
||||
+ /* We've got pending audio which hasn't been written, we must write it to
|
||||
+ the hardware, else it will never be played. */
|
||||
+ status = writeBlock(s, current);
|
||||
+ HANDLE_WAVE_ERROR(status, "writing audio to audio device");
|
||||
+ }
|
||||
+
|
||||
if (!s->playing) {
|
||||
return SA_ERROR_INVALID;
|
||||
}
|
||||
|
||||
/* wait for all blocks to complete */
|
||||
EnterCriticalSection(&(s->waveCriticalSection));
|
||||
while(s->waveFreeBlockCount < BLOCK_COUNT) {
|
||||
LeaveCriticalSection(&(s->waveCriticalSection));
|
||||
@@ -502,16 +515,48 @@ int closeAudio(sa_stream_t * s) {
|
||||
|
||||
s->playing = 0;
|
||||
|
||||
DeleteCriticalSection(&(s->waveCriticalSection));
|
||||
CloseHandle(s->callbackEvent);
|
||||
|
||||
return result;
|
||||
}
|
||||
+
|
||||
+/**
|
||||
+ * \brief - writes a WAVEHDR block of PCM audio samples to hardware.
|
||||
+ * \param s - valid handle to opened sydney stream
|
||||
+ * \param current - pointer to WAVEHDR storing audio samples to be played
|
||||
+ * \return - completion status
|
||||
+ */
|
||||
+int writeBlock(sa_stream_t *s, WAVEHDR* current) {
|
||||
+ int status;
|
||||
+ ERROR_IF_NO_INIT(s);
|
||||
+
|
||||
+ current->dwBufferLength = current->dwUser;
|
||||
+ /* write to audio device */
|
||||
+ waveOutPrepareHeader(s->hWaveOut, current, sizeof(WAVEHDR));
|
||||
+ status = waveOutWrite(s->hWaveOut, current, sizeof(WAVEHDR));
|
||||
+ HANDLE_WAVE_ERROR(status, "writing audio to audio device");
|
||||
+
|
||||
+ EnterCriticalSection(&(s->waveCriticalSection));
|
||||
+ s->waveFreeBlockCount--;
|
||||
+ LeaveCriticalSection(&(s->waveCriticalSection));
|
||||
+
|
||||
+ /*
|
||||
+ * point to the next block
|
||||
+ */
|
||||
+ (s->waveCurrentBlock)++;
|
||||
+ (s->waveCurrentBlock) %= BLOCK_COUNT;
|
||||
+
|
||||
+ s->playing = 1;
|
||||
+
|
||||
+ return SA_SUCCESS;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* \brief - writes PCM audio samples to audio device
|
||||
* \param s - valid handle to opened sydney stream
|
||||
* \param data - pointer to memory storing audio samples to be played
|
||||
* \param nsamples - number of samples in the memory pointed by previous parameter
|
||||
* \return - completion status
|
||||
*/
|
||||
int writeAudio(sa_stream_t *s, LPSTR data, int bytes) {
|
||||
@@ -536,40 +581,27 @@ int writeAudio(sa_stream_t *s, LPSTR dat
|
||||
|
||||
if(bytes < (int)(BLOCK_SIZE - current->dwUser)) {
|
||||
memcpy(current->lpData + current->dwUser, data, bytes);
|
||||
current->dwUser += bytes;
|
||||
break;
|
||||
}
|
||||
|
||||
/* remain is even as BLOCK_SIZE and dwUser are even too */
|
||||
- remain = BLOCK_SIZE - current->dwUser;
|
||||
+ remain = BLOCK_SIZE - current->dwUser;
|
||||
memcpy(current->lpData + current->dwUser, data, remain);
|
||||
+ current->dwUser += remain;
|
||||
bytes -= remain;
|
||||
data += remain;
|
||||
- current->dwBufferLength = BLOCK_SIZE;
|
||||
- /* write to audio device */
|
||||
- waveOutPrepareHeader(s->hWaveOut, current, sizeof(WAVEHDR));
|
||||
- status = waveOutWrite(s->hWaveOut, current, sizeof(WAVEHDR));
|
||||
+
|
||||
+ status = writeBlock(s, current);
|
||||
HANDLE_WAVE_ERROR(status, "writing audio to audio device");
|
||||
-
|
||||
- EnterCriticalSection(&(s->waveCriticalSection));
|
||||
- s->waveFreeBlockCount--;
|
||||
- LeaveCriticalSection(&(s->waveCriticalSection));
|
||||
-
|
||||
- /*
|
||||
- * point to the next block
|
||||
- */
|
||||
- (s->waveCurrentBlock)++;
|
||||
- (s->waveCurrentBlock) %= BLOCK_COUNT;
|
||||
|
||||
current = &(s->waveBlocks[s->waveCurrentBlock]);
|
||||
current->dwUser = 0;
|
||||
-
|
||||
- s->playing = 1;
|
||||
}
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief - audio callback function called when next WAVE header is played by audio device
|
||||
*/
|
||||
void CALLBACK waveOutProc(
|
@ -126,6 +126,7 @@ int allocateBlocks(int size, int count, WAVEHDR** blocks);
|
||||
int freeBlocks(WAVEHDR* blocks);
|
||||
int openAudio(sa_stream_t *s);
|
||||
int closeAudio(sa_stream_t * s);
|
||||
int writeBlock(sa_stream_t *s, WAVEHDR* current);
|
||||
int writeAudio(sa_stream_t *s, LPSTR data, int bytes);
|
||||
int getSAErrorCode(int waveErrorCode);
|
||||
|
||||
@ -325,10 +326,22 @@ int sa_stream_pause(sa_stream_t *s) {
|
||||
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
||||
/** Block until all audio has been played */
|
||||
int sa_stream_drain(sa_stream_t *s) {
|
||||
int status;
|
||||
WAVEHDR* current;
|
||||
|
||||
ERROR_IF_NO_INIT(s);
|
||||
|
||||
|
||||
current = &(s->waveBlocks[s->waveCurrentBlock]);
|
||||
if (current->dwUser) {
|
||||
/* We've got pending audio which hasn't been written, we must write it to
|
||||
the hardware, else it will never be played. */
|
||||
status = writeBlock(s, current);
|
||||
HANDLE_WAVE_ERROR(status, "writing audio to audio device");
|
||||
}
|
||||
|
||||
if (!s->playing) {
|
||||
return SA_ERROR_INVALID;
|
||||
}
|
||||
@ -507,6 +520,38 @@ int closeAudio(sa_stream_t * s) {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief - writes a WAVEHDR block of PCM audio samples to hardware.
|
||||
* \param s - valid handle to opened sydney stream
|
||||
* \param current - pointer to WAVEHDR storing audio samples to be played
|
||||
* \return - completion status
|
||||
*/
|
||||
int writeBlock(sa_stream_t *s, WAVEHDR* current) {
|
||||
int status;
|
||||
ERROR_IF_NO_INIT(s);
|
||||
|
||||
current->dwBufferLength = current->dwUser;
|
||||
/* write to audio device */
|
||||
waveOutPrepareHeader(s->hWaveOut, current, sizeof(WAVEHDR));
|
||||
status = waveOutWrite(s->hWaveOut, current, sizeof(WAVEHDR));
|
||||
HANDLE_WAVE_ERROR(status, "writing audio to audio device");
|
||||
|
||||
EnterCriticalSection(&(s->waveCriticalSection));
|
||||
s->waveFreeBlockCount--;
|
||||
LeaveCriticalSection(&(s->waveCriticalSection));
|
||||
|
||||
/*
|
||||
* point to the next block
|
||||
*/
|
||||
(s->waveCurrentBlock)++;
|
||||
(s->waveCurrentBlock) %= BLOCK_COUNT;
|
||||
|
||||
s->playing = 1;
|
||||
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief - writes PCM audio samples to audio device
|
||||
* \param s - valid handle to opened sydney stream
|
||||
@ -541,30 +586,17 @@ int writeAudio(sa_stream_t *s, LPSTR data, int bytes) {
|
||||
}
|
||||
|
||||
/* remain is even as BLOCK_SIZE and dwUser are even too */
|
||||
remain = BLOCK_SIZE - current->dwUser;
|
||||
remain = BLOCK_SIZE - current->dwUser;
|
||||
memcpy(current->lpData + current->dwUser, data, remain);
|
||||
current->dwUser += remain;
|
||||
bytes -= remain;
|
||||
data += remain;
|
||||
current->dwBufferLength = BLOCK_SIZE;
|
||||
/* write to audio device */
|
||||
waveOutPrepareHeader(s->hWaveOut, current, sizeof(WAVEHDR));
|
||||
status = waveOutWrite(s->hWaveOut, current, sizeof(WAVEHDR));
|
||||
HANDLE_WAVE_ERROR(status, "writing audio to audio device");
|
||||
|
||||
EnterCriticalSection(&(s->waveCriticalSection));
|
||||
s->waveFreeBlockCount--;
|
||||
LeaveCriticalSection(&(s->waveCriticalSection));
|
||||
|
||||
/*
|
||||
* point to the next block
|
||||
*/
|
||||
(s->waveCurrentBlock)++;
|
||||
(s->waveCurrentBlock) %= BLOCK_COUNT;
|
||||
status = writeBlock(s, current);
|
||||
HANDLE_WAVE_ERROR(status, "writing audio to audio device");
|
||||
|
||||
current = &(s->waveBlocks[s->waveCurrentBlock]);
|
||||
current->dwUser = 0;
|
||||
|
||||
s->playing = 1;
|
||||
}
|
||||
return SA_SUCCESS;
|
||||
}
|
||||
|
@ -15,3 +15,4 @@ patch -p3 <bug525401_drain_deadlock.patch
|
||||
patch -p3 <bug526411_latency.patch
|
||||
patch -p3 <sydney_aix.patch
|
||||
patch -p3 <bug562488_oss_destroy_crash.patch
|
||||
patch -p3 <bug564734-win32-drain.patch
|
||||
|
Loading…
Reference in New Issue
Block a user