----------------------------------------------------------------------------
WARNING: long mail follows.
One-line summary:
HEAD broken. Sorry for that. I'm already testing the patch, stay tuned!
-----------------------------------------------------------------------------

On Tue, 2008-12-30 at 08:31 -0700, William Astle wrote:
> > This means a new RC out in a few weeks and (hopefully) the 1.1.0 final
> > a few weeks after.

Still working on that.
I've committed a preliminary and already quite big patch on both HEAD
and 1.1.0 branches. Looks like I'm on the right track (I consider the
new code better in any way with respect to old one, and I wrote both of
them, so this isn't geek pride ;))

But, everybody knows: new code, new bugs[0]. Found yet another one when
doing further testing. I've the code which fixes that (and improves
the code and the design again), but until I commit that

*BOTH* HEAD and 1.1.0 ARE BUGGY! <<======

(I'm sorry for tainting HEAD, that was not made by purpose)

Feel free to ask me the gory details if you like.
A short (!) summary follows.

+++

The root of the problem is the following:

the filter layer not guarantee the in-order deliver of frames to export
layer, because it's multithreaded and has not ordering-enforcing code
(yet).

Let's consider a four-frames long stream.

Import layer delivers frames 1-2-3-4.
Filter layer got them in frame order (import has one thread per stream
and intrinsecally work in FIFO discipline. And we're all very happy with
that).

Filter layer uses N threads per stream. The thread can finish in any
order, so they can deliver the frames to export in any order.
But export expects frames in-order!

An order as returned by filter layer can be 1-2-3-4, 4-3-2-1, 1-3-2-4,
any combination is legal.

Formerly, the linked list placed on the framebuffer was ensuring the
correct order. But that data model was ugly for a number of reasons,
first and foremost duplicating a significant amount of code (private
linked list implementation, using extra fields in frame structure).

Now, no more linked list. How to deal with out-of-order deliver?

I've initially thought (and I'm still convinced that is possible, that's
the most efficient solution and it's also quite elegant) that it is
possible to use a pseudo-sliding-window procedure
(http://en.wikipedia.org/wiki/Sliding_window), having implicit ordering.
The export buffers become a sort of rotating sliding window (so, a
sliding window implemented using a ring buffer),
no longer a plain old FIFO. So filter layer can deliver the completed
frames directly into the correct slot without hassle and, as said, with
implicit ordering. And maximum efficiency.

Uhm, clever! Probably too clever. That's hard to explain (so hard to
document, hard understand, hard to hack, and that's Bad. Very Bad.),
and most important the current implementation is the result of various
simplifications of the sliding window algorhytm... Which ends up to bugs
[1] :)

Solution (currently being tested on my local tree): step back, humilty,
drop all this supposed cleverness and implement an heap buffer 
(http://en.wikipedia.org/wiki/Binary_heap) for the export, and only for
the export.
Heap is simple, well known, easy to grok, efficient enough. Is not O(1)
for insertion and extraction as the sliding window idea was *supposed*
to be, but it's still fast for our common case, yet flexible enough for
future changes. And someday both FIFO and heap can be extracted,
generalized and put into libtc(util) with minimal effort.

Ok, that's all for the short summary :)

Discussion welcome.

+++

[0] I was not satisfied with the old framebuffer. The code was
redundant, crufty, too complex *AND* already buggy at very least for PSU
mode. Given the overall situation it's pointless to be on schedule but
with bugs like that. So, let's bite the bullet and let's do something
better.

[1] Which ultimately is:
current code places incoming frames into the export buffer in the
position corresponding to frame's bufid. The bufid is the internal ID of
a framebuffer, corresponding to the frame registration order. Nothing
else.
Nobody, except a series of circumstances, guarantees that 

frame_id % frame_ring_size = frame_bufid (hard constraint)

Or even that

the bufid sequence seen by export is monotonically increasing (soft
constraint)

But the root of the problem is on the algorythimic side: the buffer
handling code should make it's decisions on public fields, most
important being the frame sequence number (=id) in order to be robust
and flexible.


-- 
Francesco Romani // Ikitt
http://fromani.exit1.org  ::: transcode homepage
http://tcforge.berlios.de ::: transcode experimental forge

Reply via email to