[MPlayer-dev-eng] [PATCH] ao_dart
Reimar Döffinger
Reimar.Doeffinger at stud.uni-karlsruhe.de
Mon Feb 23 11:10:38 CET 2009
On Mon, Feb 23, 2009 at 06:13:26PM +0900, KO Myung-Hun wrote:
> +static volatile int m_nBufSize = 0;
> +static volatile int m_nBufLen = 0;
> +static volatile int m_iBufPos = 0;
I would propose an ordinary buffer instead of a FIFO, i.e. without using
m_iBufPos.
> +static ULONG APIENTRY dart_audio_callback(PVOID pCBData, PVOID pBuffer,
> + ULONG ulSize)
> +{
> + int nCopySize;
> + ULONG rc;
> +
> + do {
> + rc = DosRequestMutexSem(m_hmtxBuf, SEM_INDEFINITE_WAIT);
> + } while (rc == ERROR_INTERRUPT);
> +
> + nCopySize = ulSize < m_nBufLen ? ulSize : m_nBufLen;
> +
> + if (m_iBufPos + nCopySize > m_nBufSize) {
> + int len = m_nBufSize - m_iBufPos;
> +
> + fast_memcpy(pBuffer, m_audioBuf + m_iBufPos, len);
> + fast_memcpy((uint8_t *)pBuffer + len, m_audioBuf, nCopySize - len);
> + }
> + else
> + fast_memcpy(pBuffer, m_audioBuf + m_iBufPos, nCopySize);
> +
> + m_iBufPos = (m_iBufPos + nCopySize) % m_nBufSize;
> + m_nBufLen -= nCopySize;
> +
> + memset((uint8_t *)pBuffer + nCopySize, DART.bSilence, ulSize - nCopySize);
> +
> + DosReleaseMutexSem(m_hmtxBuf);
(include libavutil/common.h to get FFMIN)
(get mutex)
nCopySize = FFMIN(ulSize, m_nBufLen);
fast_memcpy(pBuffer, m_audioBuf, nCopySize);
m_nBufLen -= nCopySize;
if (m_nBufLen)
fast_memcpy(m_audioBuf, m_audioBuf + nCopySize, m_nBufLen);
(release mutex, return nCopySize)
> +// return: how many bytes can be played without blocking
> +static int get_space(void)
> +{
> + return m_nBufSize - m_nBufLen;
> +}
Since you use locking anyway, it would be safer to lock here, too.
And yes, reads need to be locked, too. The reason is that a Mutex does
not create a atomic operation, it just makes sure that you will not be
interrupted by code that is _also_ inside a mutex.
So e.g. adding a mutex over only one piece of code will not have any
effect at all, that would only work on the OS level when you disable
interrupts instead of using a Mutex.
Keep in mind that OS/2 probably only provides very simple mutexes, so
you may not call get_space from play or dart_audio_callback after
adding Mutex code here.
> + do {
> + rc = DosRequestMutexSem(m_hmtxBuf, SEM_INDEFINITE_WAIT);
> + } while (rc == ERROR_INTERRUPT);
> +
> + start_pos = ( m_iBufPos + m_nBufLen ) % m_nBufSize;
> +
> + end_pos = (start_pos + len) % m_nBufSize;
> + if (end_pos <= start_pos) {
> + int len1 = m_nBufSize - start_pos;
> +
> + if (end_pos > m_iBufPos)
> + end_pos = m_iBufPos;
> +
> + fast_memcpy(m_audioBuf + start_pos, data, len1);
> + fast_memcpy(m_audioBuf, (uint8_t *)data + len1, end_pos);
> +
> + len = len1 + end_pos;
> + }
> + else
> + fast_memcpy(m_audioBuf + start_pos, data, len);
> +
> + m_nBufLen += len;
> +
> + DosReleaseMutexSem(m_hmtxBuf);
This is basically why I suggested simplifying and getting rid of the
code. You at least miss a check on len, e.g. for len = m_nBufSize + 1
you would happily write beyond the bounds of the buffer causing a buffer
overflow. Since MPlayer checks the free space beforehand, this is
unlikely to happen currently but still wrong.
Suggested replacement code:
(get mutex)
len = FFMIN(len, m_nBufSize - m_nBufLen);
fast_memcpy(m_audioBuf + m_nBufLen, data, len);
m_nBufLen += len;
(release mutex, return len)
> +// return: delay in seconds between first and last sample in buffer
> +static float get_delay(void)
> +{
> + return (float)m_nBufLen / (float)ao_data.bps;
> +}
Locking here will avoid surprises in the future, too.
More information about the MPlayer-dev-eng
mailing list