[MPlayer-dev-eng] Lots of stuff for NUT

Oded Shimon ods15 at ods15.dyndns.org
Sat Jan 14 08:28:00 CET 2006


On Sat, Jan 14, 2006 at 02:06:01AM +0100, Michael Niedermayer wrote:
> Hi
> 
> On Sat, Jan 14, 2006 at 12:34:55AM +0200, Oded Shimon wrote:
> > On Fri, Jan 13, 2006 at 11:25:39PM +0100, Michael Niedermayer wrote:
> [...]
> > > > > > Since (I think) we have completely prooved that both methods are 100% 
> > > > > > working, the tradeoff here is purely:
> > > > > > 1. complexity and allowing several syncpoints with no frame inbetween
> > > > > > 2. overhead of (most likely) 1 byte per syncpoint for almost any file
> > > > > > 
> > > > > > My vote is still 2, and I have a feeling Rich will flame on the several 
> > > > > > syncpoints thing, however I'm gonna start implementing single ts, and if 
> > > > > > Rich agrees with it then I'm OK with finalizing it...
> > > > 
> > > > OK, umm, I'm trying, but as I feared it is getting increasingly much more 
> > > > complicated, especially the interleaved dts cache flushing part... I'm 
> > > > still highly suggesting multiple ts. The overhead is REALLY not an issue 
> > > > now, so it's not an excuse IMO... (You do remember that it is as many ts's 
> > > > as the amount of delay>0 streams, plus one, right? So rarely EVER is more 
> > > > than two ts necessary..)
> > > 
> > > the flushing is needed anyway, if you want delay>0 EORs as 1in 1out decoders
> > > need the extra packets to output anything and for delay=0 EORs theres no
> > > flushing if i understand it correctly so really i cant see how multiple ts
> > > are going to simplify anything here ...
> > 
> > With multiple ts there is no interleaved cache flushing that causes 
> > syncpoints. There isn't even any possible situation of 2 syncpoints with no 
> > frames inbetween. I finished all the code necessary for multiple ts for the 
> > nut_write_frame() code in 5 lines:
> > 
> > 
> > <after writing frame data>
> > if (is_key) {
> >         old_back_ptr = stream->back_ptr;
> >         stream->back_ptr = nut->last_syncpoint;
> >         if (nut->last_syncpoint != old_back_ptr) stream->key_pts = pts;
> >         if (old_back_ptr - nut->last_syncpoint > nut->max_distance) put_syncpoint();
> > }
> > 
> > 
> > Now all you have to do in the syncpoint is grab all stream->key_pts and 
> > stream->back_ptr, compress and output!.. Certainely much simpler than what 
> > I'm still trying to implement here.. :/
> 
> hmm, what about a method which stores <= 1+num of non 0 delay pts
> i mean we only need to store a pts for a delay>0 stream if its pts is >
> the SP TS or something like that i think

Well, doable. Coding it in syncpoint is tricky though... You'll most likely 
have to add atleast 1 byte to say which streams you are coding for, which 
is about the amount of bytes necessary anyway.

BTW, syncpoint needs to handle the case of "only non 0 delay streams" 
gracefully, as in, not waste a coded pts in the begginning for nothing...

OK, I think I've got a good spec, it codes it most efficiently...

syncpoint:
    startcode                               u(64)
    coded_pts                               v
    stream= coded_pts % stream_count
    global_key_pts= coded_pts/stream_count
    n= 0
    cache[n++]= 0
    cache[n++]= back_ptr[stream]            v
    A= 0
    for (i=0; i<stream_count; i++) {
        if (i==stream) continue
        if (A==0) A                         v
        if (decode_delay[i]) {
            if (non_delayed_streams) {
                flag=A&1
                A>>= 1
            } else flag=1
            if (flag) {
                key_pts[i] = A
                A                           v
            }
        }
        if ((stream==stream_count-1 && i==stream_count-2)
             || i==stream_count-1) {
            if (A>=n) back_ptr[i]= A-n
            else back_ptr[i]= cache[A]
        } else {
            if (A&1) {
                A>>= 1
                j= A%n;
                A/= n;
            } else {
                cache[n]= A>>1
                j= n++
                A= 0
            }
            back_ptr[i]= cache[j]
        }
    }


global_key_pts is:
1. if there are non delayed streams in the file, the max pts of all those 
streams
2. if there aren't, the min pts of all streams.

key_pts must be coded if it is higher than global_key_pts, or if there are 
no non delayed streams. key_pts is relative to global_key_pts, and always 
larger, so sign is not necessary.

You could say all of this is complex, but it is only localized complexity 
to coding data most efficiently in the syncpoint... And IMO it's still less 
complex than the second solution... (uau actually managed to get me a 
rather nice implementation involving caching keyframes which changed 
back_ptr, however it is still rather complicated..) Also storing several 
syncpoints in same locations is just wrong. :/

Overhead is truely not an excuse now, it's a single bit!

- ods15




More information about the MPlayer-dev-eng mailing list