Re: libmng data-push mechanism(s)

"Gerard Juyn" <gjuyn-qWit8jRvyhVmR6Xm/[email protected]> Fri, 9 Apr 2004 09:48:06 +0100
Newsgroups gmane.comp.graphics.mng.general
Message-ID <40767156.1903.3FD8E8@localhost>
> how does libpng work on this point?

I haven't a clue....
 
> But how I understand the mozilla source ... we need to read out the
> buffer every round ... but why we don't let read libmng the next
> (<=)1024 bytes in hits own buffer if mng_display_resume is called. It
> now reads also in 1024 Byte parts in the own buffer?

That's because you (or rather tor) have turned on suspension mode. In this 
way libmng will keep an internal 32K buffer and reads 1K blocks at a time. So 
this is contrarary to what I said earlier about alwasy reading the 4-byte length 
and then the chunk, 4byte length, next chunk,etc. It is still doing that internally 
but there's an extra (relatively small) buffer in between.
 
> Also if you start with mng_read then mng_read_resume always reads more
> from stream and then you also can do mng_display to start displaying.
> But I wan't displaying while file is read from web :-) (And also in this
> way I don't know if the file in stream have ended or the buffer isn't
> filled enough and so I don't know if I can call mng_display)

In Mozilla I'd keep to the read&display at the same time. So to speak, because 
it's obviously not doing it at exactly the same time but interspersed. Which is 
exactly why it's so freakish complicated :(

The mechanism I'm proposing, and that Ralph has extended on with a 
"release" callback (which is a brilliant idea btw!) will do everything you need:

mnt_retcode libmng_read_pushdata (mng_handle hHandle,
					mng_ptr pData,
					mng_size_t iLength,
					mng_bool bTakeownership);

mng_retcode libmng_read_pushchunk (mng_handle hHandle,
					mng_ptr pChunk,
					mng_size_t iLength,
					mng_bool bTakeownership);

typedef void (*mng_releasedata) (mng_ptr pUserdata,
					mng_ptr pData,
					mng_size_t iLength);
mng_retcode mng_setcb_releasedata (mng_handle hHandle,
					mng_releasedata fProc);

The first function is used with arbitrary blocks of data streaming in. The 
second is specific for where the encompassing decoder already knows it's 
dealing with chunks (eg. the length and optionally crc are already processed; 
crc processing inside libmng is now decided by the libmng_set_crcmode() 
call; this is true for both methods *and* when using the pull mechanism!).
So data-wise the only real difference is that with the second function the 
data *does not* hold the chunk-length value.

I've split them up because libmng can process the second type much easier ;)
In theory one could use both methods, but internally libmng will first deplete 
the 'chunk' buffer and then the 'data' buffer, so things could potentially get 
mixed up. Eg DON'T use both.

If bTakeownership == MNG_TRUE, libmng will keep the pointer/length and 
disperse the buffer when it's been processed completely. If the third function 
was used to set a specific callback for this purpose that will be used, 
otherwise the default freeing mechanism will be called (which may in turn 
resort to a callback!).

If bTakeownership == MNG_FALSE, libmng will create a new buffer and copy 
the provided contents across (and obviously will automatically free the 
created buffer once processed).

I think I'll leave the current mechanism as-is, which means even using one of 
the push mechanisms, you still have to supply a readdata() callback. This will 
be called when all internally buffered data has been processed. But this 
callback can just simply always return '0 bytes read', in which case libmng 
will fall back into the normal needmoredata wait-state. Once you've received 
more data and pushed it in, you can call display_resume() as usual.

Alex, in the push mode, you'll have to turn suspension mode off, or better said 
*don't* turn it on (the default is off). The whole idea with that becomes moot 
with this mechanism, and would just complicate things too much.

Gerard

ps. some nasty tricks become available too... a regular decoder using the 
normal pull mechanism could actually use the push calls to insert data at any 
given moment without changing the input-stream. It would require some clever 
timing, but it's possible. Say you always want to add the same BACK chunk if 
none is supplied, you'd call pushchunk() during the processheader() callback 
with a properly formatted BACK chunk (without the length but with crc; if 
you're processing crc's...), et voila! And I'm sure smarter people than me can 
come up with lots of other ideas....:)


--
Send the message body "help" to [email protected]