[Openal-devel] PING: Queueing fails for buffers with streamed
sources
Chris Robinson
chris.kcat at gmail.com
Mon May 21 12:36:26 PDT 2007
On Friday 11 May 2007 09:43:12 am Devils-Hawk wrote:
> Did send this a while ago just pinging for comments:
>
> Using svn revision 1426 under linux when running something like:
>
> alGenBuffers( 2, vorbbuf );
> alGenSources( 1, &vorbsource );
> alSourceQueueBuffers(vorbsource,2,vorbbuf);
> alutLoadVorbisp( vorbbuf[i], data, size );
> alSourcePlay( vorbsource );
>
> openal plays the first buffer in an endless loop.
>
> Testcase and a patch to fix it is attached. There is probably a better
> way to do this but this seems to work.
>
> regards DevH
My apologies for not responding sooner. I'm still learning how OpenAL's
internals work.
The problems, as I see it, is that AL_EXT_vorbis wraps around
alBufferDataCallback_LOKI. The callback is called by the mixer to stream more
data into a mixer buffer on an as-needed basis. If the callback returns
negative, the source is aborted. If it returns less than the requested
samples, it sets the soundpos to the "end" of the buffer to trigger a stop,
or whatever the source is intended to do (which is a bit clumsy because a
stream that's an exact multiple of the internal buffer size may never return
less than the requested buffer size; or if a data stream is starved (eg.
network latency) it could return less, but not intend to stop).
However, after the data received from the callback is deinterleaved, the
stored size counter is incremented which pushes it past where sourcepos was
set to. The next iteration then sees that there's more data waiting, and sees
its a callback buffer, so it proceeds and requests more data, repeating
again. Because it may be expecting to loop, the callback function resets the
compressed stream back to the beginning and keeps playing.
Given how the callback extension is, I don't believe it was intended to work
in conjunction with a queue. Or if it was, there's been changes in the 1.1
spec that makes it difficult, if not impossible, to properly handle.
With a buffer queue, when each buffer completes, it marks it as processed and
moves on. However with a callback, the buffer has no completion point. It
just eventually runs out of data. Also you have something like
AL_SAMPLE_OFFSET which, when set on a source with queued buffers, is supposed
to skip buffers it's offset past (marking them as processed).. but a callback
buffer has no set size, so it can't know whether it skips by it or not, nor
is there a method to skip in a data stream.
Put simply, buffer callbacks and buffer queues are two methods to do the same
thing (stream data that's too big to put into a single buffer, using smaller
buffers). What ends up happening in your program is that it uses a streaming
method on top of a streaming method.
I think it would be prudent to disallow a callback buffer to be queued.
Actually I think a better solution would be to drop
AL_LOKI_buffer_data_callback, and revise the AL_EXT_vorbis (and other
compressed format) specs to make it more apparent that it's streaming. IMO,
of course.
More information about the Openal-devel
mailing list