зеркало из https://github.com/mozilla/pjs.git
Bug 564734 - Ensure all audio is queued before draining on win32. r=kinetik
This commit is contained in:
Родитель
0ef41b1ade
Коммит
eda6280198
|
@ -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
|
sydney_aix.patch: Bug 499266 - add support for AIX 5.x
|
||||||
|
|
||||||
bug562488_oss_destroy_crash.patch: Fix crash in OSS backend when destroying stream.
|
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.
|
|
@ -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 freeBlocks(WAVEHDR* blocks);
|
||||||
int openAudio(sa_stream_t *s);
|
int openAudio(sa_stream_t *s);
|
||||||
int closeAudio(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 writeAudio(sa_stream_t *s, LPSTR data, int bytes);
|
||||||
int getSAErrorCode(int waveErrorCode);
|
int getSAErrorCode(int waveErrorCode);
|
||||||
|
|
||||||
|
@ -325,10 +326,22 @@ int sa_stream_pause(sa_stream_t *s) {
|
||||||
|
|
||||||
return SA_SUCCESS;
|
return SA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Block until all audio has been played */
|
/** Block until all audio has been played */
|
||||||
int sa_stream_drain(sa_stream_t *s) {
|
int sa_stream_drain(sa_stream_t *s) {
|
||||||
|
int status;
|
||||||
|
WAVEHDR* current;
|
||||||
|
|
||||||
ERROR_IF_NO_INIT(s);
|
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) {
|
if (!s->playing) {
|
||||||
return SA_ERROR_INVALID;
|
return SA_ERROR_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -507,6 +520,38 @@ int closeAudio(sa_stream_t * s) {
|
||||||
|
|
||||||
return result;
|
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
|
* \brief - writes PCM audio samples to audio device
|
||||||
* \param s - valid handle to opened sydney stream
|
* \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 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);
|
memcpy(current->lpData + current->dwUser, data, remain);
|
||||||
|
current->dwUser += remain;
|
||||||
bytes -= remain;
|
bytes -= remain;
|
||||||
data += 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));
|
|
||||||
|
|
||||||
/*
|
status = writeBlock(s, current);
|
||||||
* point to the next block
|
HANDLE_WAVE_ERROR(status, "writing audio to audio device");
|
||||||
*/
|
|
||||||
(s->waveCurrentBlock)++;
|
|
||||||
(s->waveCurrentBlock) %= BLOCK_COUNT;
|
|
||||||
|
|
||||||
current = &(s->waveBlocks[s->waveCurrentBlock]);
|
current = &(s->waveBlocks[s->waveCurrentBlock]);
|
||||||
current->dwUser = 0;
|
current->dwUser = 0;
|
||||||
|
|
||||||
s->playing = 1;
|
|
||||||
}
|
}
|
||||||
return SA_SUCCESS;
|
return SA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,3 +15,4 @@ patch -p3 <bug525401_drain_deadlock.patch
|
||||||
patch -p3 <bug526411_latency.patch
|
patch -p3 <bug526411_latency.patch
|
||||||
patch -p3 <sydney_aix.patch
|
patch -p3 <sydney_aix.patch
|
||||||
patch -p3 <bug562488_oss_destroy_crash.patch
|
patch -p3 <bug562488_oss_destroy_crash.patch
|
||||||
|
patch -p3 <bug564734-win32-drain.patch
|
||||||
|
|
Загрузка…
Ссылка в новой задаче