Fixed: infinite loop in ogg vorbis streaming (negative ov_read result means an error)

This commit is contained in:
kervala 2010-08-17 23:02:47 +02:00
parent fd2e238e6c
commit 585b053040
2 changed files with 41 additions and 21 deletions

View file

@ -120,40 +120,59 @@ uint32 CMusicBufferVorbis::getRequiredBytes()
uint32 CMusicBufferVorbis::getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum) uint32 CMusicBufferVorbis::getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum)
{ {
int current_section = 0; // ??? sint current_section = 0; // ???
if (_IsMusicEnded) return 0; if (_IsMusicEnded) return 0;
nlassert(minimum <= maximum); // can't have this.. nlassert(minimum <= maximum); // can't have this..
uint32 bytes_read = 0; uint32 bytes_read = 0;
do do
{ {
// signed 16-bit or unsigned 8-bit little-endian samples // signed 16-bit or unsigned 8-bit little-endian samples
int br = ov_read(&_OggVorbisFile, (char *)&buffer[bytes_read], maximum - bytes_read, sint br = ov_read(&_OggVorbisFile, (char *)&buffer[bytes_read], maximum - bytes_read,
0, // Specifies big or little endian byte packing. 0 for little endian, 1 for b ig endian. Typical value is 0. 0, // Specifies big or little endian byte packing. 0 for little endian, 1 for b ig endian. Typical value is 0.
getBitsPerSample() == 8 ? 1 : 2, getBitsPerSample() == 8 ? 1 : 2,
getBitsPerSample() == 8 ? 0 : 1, // Signed or unsigned data. 0 for unsigned, 1 for signed. Typically 1. getBitsPerSample() == 8 ? 0 : 1, // Signed or unsigned data. 0 for unsigned, 1 for signed. Typically 1.
&current_section); &current_section);
// nlinfo(NLSOUND_XAUDIO2_PREFIX "current_section: %i", current_section); // nlinfo(NLSOUND_XAUDIO2_PREFIX "current_section: %i", current_section);
if (br <= 0) if (br > 0)
{ {
if (br == 0) bytes_read += (uint32)br;
}
else if (br == 0) // EOF
{
if (_Loop)
{ {
if (_Loop) ov_pcm_seek(&_OggVorbisFile, 0);
{ //_Stream->seek(0, NLMISC::IStream::begin);
ov_pcm_seek(&_OggVorbisFile, 0);
//_Stream->seek(0, NLMISC::IStream::begin);
}
else
{
_IsMusicEnded = true;
break;
}
} }
else else
{ {
nlwarning("ov_read: %i", br); _IsMusicEnded = true;
break;
} }
} }
else bytes_read += (uint32)br; else
{
// error
switch(br)
{
case OV_HOLE:
nlwarning("ov_read returned OV_HOLE");
break;
case OV_EINVAL:
nlwarning("ov_read returned OV_EINVAL");
break;
case OV_EBADLINK:
nlwarning("ov_read returned OV_EBADLINK");
break;
default:
nlwarning("ov_read returned %d", br);
}
return 0;
}
} while (bytes_read < minimum); } while (bytes_read < minimum);
return bytes_read; return bytes_read;
} }
@ -161,7 +180,7 @@ uint32 CMusicBufferVorbis::getNextBytes(uint8 *buffer, uint32 minimum, uint32 ma
uint8 CMusicBufferVorbis::getChannels() uint8 CMusicBufferVorbis::getChannels()
{ {
vorbis_info *vi = ov_info(&_OggVorbisFile, -1); vorbis_info *vi = ov_info(&_OggVorbisFile, -1);
return (uint16)vi->channels; return (uint8)vi->channels;
} }
uint32 CMusicBufferVorbis::getSamplesPerSec() uint32 CMusicBufferVorbis::getSamplesPerSec()

View file

@ -83,7 +83,7 @@ bool CMusicChannelAL::fillBuffer(IBuffer *buffer, uint length)
uint32 size = _MusicBuffer->getNextBytes(tmp, length, length); uint32 size = _MusicBuffer->getNextBytes(tmp, length, length);
buffer->unlock(size); buffer->unlock(size);
return true; return size > 0;
} }
/// Use buffer format from IMusicBuffer /// Use buffer format from IMusicBuffer
@ -128,7 +128,8 @@ void CMusicChannelAL::run()
// fill buffers // fill buffers
for(uint i = 0; i < buffers.size(); ++i) for(uint i = 0; i < buffers.size(); ++i)
{ {
fillBuffer(buffers[i], _Source->getStreamingBufferSize()); if (!fillBuffer(buffers[i], _Source->getStreamingBufferSize()))
break;
// add buffer to streaming buffers queue // add buffer to streaming buffers queue
_Source->submitStreamingBuffer(buffers[i]); _Source->submitStreamingBuffer(buffers[i]);