diff --git a/media/libsydneyaudio/README_MOZILLA b/media/libsydneyaudio/README_MOZILLA index dffcf16140c..cfec57638c7 100644 --- a/media/libsydneyaudio/README_MOZILLA +++ b/media/libsydneyaudio/README_MOZILLA @@ -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. \ No newline at end of file diff --git a/media/libsydneyaudio/bug564734-win32-drain.patch b/media/libsydneyaudio/bug564734-win32-drain.patch new file mode 100644 index 00000000000..af702ed93b4 --- /dev/null +++ b/media/libsydneyaudio/bug564734-win32-drain.patch @@ -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( diff --git a/media/libsydneyaudio/src/sydney_audio_waveapi.c b/media/libsydneyaudio/src/sydney_audio_waveapi.c index bc69178e74a..43ee86bc1f2 100644 --- a/media/libsydneyaudio/src/sydney_audio_waveapi.c +++ b/media/libsydneyaudio/src/sydney_audio_waveapi.c @@ -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; } diff --git a/media/libsydneyaudio/update.sh b/media/libsydneyaudio/update.sh index ca9149c76d6..be59b8adba0 100644 --- a/media/libsydneyaudio/update.sh +++ b/media/libsydneyaudio/update.sh @@ -15,3 +15,4 @@ patch -p3