[MPlayer-dev-eng] Patches for NUT

Oded Shimon ods15 at ods15.dyndns.org
Sat Feb 4 09:49:15 CET 2006


On Fri, Feb 03, 2006 at 02:21:18PM -0500, Rich Felker wrote:
> On Fri, Feb 03, 2006 at 01:05:36PM +0100, Michael Niedermayer wrote:
> > > > 
> > > > accurate compare_ts, 02-compare_ts.patch
> > 
> > there is something i dont like ...
> > we should not force a specific implementation here which this more or less
> > does, instead we should specify things more like:
> > compare_ts
> >     Compares timestamps from 2 different timebases, 
> >     if a is before b then compare_ts(a, b) = -1
> >     if a is after  b then compare_ts(a, b) =  1
> >     else                  compare_ts(a, b) =  0
> > care must be taken that this is done exactly with no rounding errors, simply
> > casting to float or double and doing the obvious a*timebase >/<= b*timebase
> > is not compliant or correct, neither is the same with integers, and
> > a*a.ts.num*b.ts.den >/<= b*b.ts.num*a.ts.den will overflow
> > one possible implementation which shouldnt overflow within the range of
> > legal timestamps and timebases is:
> > comare_ts(a, b){
> >     if (convert_ts(a, a_timebase, b_timebase) < b) return -1;
> >     if (convert_ts(b, b_timebase, a_timebase) < a) return  1;
> >     return 0;
> > }
> 
> I agree totally, this is basically what I said on irc.

fixed

> > > > remove 2^n header restriction, 03-header-repeat.patch .
> > 
> > ok
> 
> IMO the wording is slightly confusing and makes it sound like the
> headers must be repeated at EACH 2^n position.

well, it says SHOULD, not MUST, I haven't got any better ideas.. We can 
polish it later.

> > > > Regarding error recovery michael suggested, checksum for frame header etc.
> > > > I dislike it, it complicates binary search when looking for startcodes.
> > > > Rich already proposed a solution to prevent loosing the entire file - if
> > > > you see a frame with abnormally high size immediately after a syncpoint,
> > > > while reading the frame (which you have to anyway), linear search entire
> > > > area for possible syncpoint. The worst that will happen is that you'll skip
> > > > the entire damaged area in that single frame, and that's actually a good
> > > > thing...
> > 
> > ok, but that still leaves the issue with abnormally high pts and damaged pts
> > during binary search

I'm now inclined back to checksum, because checking checksum in binary 
search is much easier than varifying timestamp or any other hack.

As for damaged pts, there is no good fix for that except optional 
max_pts_diff in header... The player should just not be that 
dumb...

> Hmm..
> I'm ok with having checksums but I'd like to hear other ideas too.

We considered adding checksums and shortening startcodes to 4 bytes, but it 
makes the startcodes very silly: 0x7A56U + ((('N'<<8) + 'M')<<16)

I also considered 16 bit checksum, as adler32 is kind of a waste on 10-20 
bytes, but 16 bits is too weak. :/

Maybe we can make only syncpoint startcode 32 bits? It's not ideal, but it 
does somehow make sense as this startcode is the only one with checksum 
immediately following it, making the checksum practically part of the 
startcode.

- ods15
-------------- next part --------------
--- mpcf.txt	2006-02-03 08:22:53.000000000 +0200
+++ mpcf.1.txt	2006-02-03 08:50:02.000000000 +0200
@@ -1,5 +1,5 @@
 ========================================
-NUT Open Container Format DRAFT 20060120
+NUT Open Container Format DRAFT 20060203
 ========================================
 
 
@@ -249,8 +249,14 @@
             for(; j<n && j<syncpoints; j++){
                 if (!has_keyframe[j][i]) continue
                 A                           v
-                last_pts += A
-                keyframe_pts[j][i] = last_pts
+                if(!A){
+                    A                       v
+                    B                       v
+                    eor_pts[j][i] = last_pts + A + B
+                }else
+                    B=0
+                keyframe_pts[j][i] = last_pts + A
+                last_pts += A + B
             }
         }
     }
@@ -557,7 +563,11 @@
 
 keyframe_pts
     The pts of the first keyframe for this stream in the region between the
-    2 syncpoints, in the stream's timebase.
+    2 syncpoints, in the stream's timebase. (EOR frames are also keyframes)
+
+eor_pts
+    Coded only if EOR is set at the position of the syncpoint. The pts of
+    that EOR. EOR is unset by the first keyframe after it.
 
 index_ptr
     Length in bytes from the first byte of the index startcode to the first
-------------- next part --------------
--- mpcf.1.txt	2006-02-03 08:50:02.000000000 +0200
+++ mpcf.2.txt	2006-02-04 10:14:38.000000000 +0200
@@ -413,6 +413,24 @@
     Note: this calculation MUST be done with unsigned 64 bit integers, and
     is equivalent to (ln*sn)/(d1*d2) but this would require a 96bit integer
 
+compare_ts
+    Compares timestamps from 2 different timebases,
+    if a is before b then compare_ts(a, b) = -1
+    if a is after  b then compare_ts(a, b) =  1
+    else                  compare_ts(a, b) =  0
+
+    Care must be taken that this is done exactly with no rounding errors,
+    simply casting to float or double and doing the obvious
+    a*timebase > b*timebase is not compliant or correct, neither is the
+    same with integers, and
+    a*a_timebase.num*b_timebase.den > b*b_timebase.num*a_timebase.den
+    will overflow. One possible implementation which shouldn't overflow
+    within the range of legal timestamps and timebases is:
+
+    if (convert_ts(a, a_timebase, b_timebase) < b) return -1;
+    if (convert_ts(b, b_timebase, a_timebase) < a) return  1;
+    return 0;
+
 msb_pts_shift
     amount of bits in lsb_pts
     MUST be <16
-------------- next part --------------
--- mpcf.2.txt	2006-02-04 10:14:38.000000000 +0200
+++ mpcf.3.txt	2006-02-04 10:14:08.000000000 +0200
@@ -677,7 +677,7 @@
 
 headers may be repeated, but if they are, then they MUST all be repeated
 together and repeated headers MUST be identical
-headers MAY only repeat at the closest possible positions after 2^x where x is
+headers SHOULD repeat at the closest possible positions after 2^x where x is
 an integer and the file end, so the headers may be repeated at 4102 if that is
 the closest position after 2^12=4096 at which the headers can be placed
 
-------------- next part --------------
--- mpcf.3.txt	2006-02-04 10:14:08.000000000 +0200
+++ mpcf.4.txt	2006-02-04 10:14:23.000000000 +0200
@@ -299,7 +299,7 @@
 
 file:
     file_id_string
-    while(!eof && next_code != index_startcode){
+    while(!eof){
         main_header
         for(i=0; i<stream_count; i++){
             if(next_packet==video_stream_header)
@@ -312,14 +312,16 @@
         while(next_code == info_startcode){
             info_packet
         }
-        while(next_code != main_startcode){
+        if(next_code == index_startcode){
+            index
+        }
+        if (!eof) while(next_code != main_startcode){
             if(next_code == syncpoint_startcode)
                 syncpoint
             frame
         }
     }
-    if (next_code == index_startcode){
-        index
+    if (has_index){
         index_ptr                       u(64)
     }
 
@@ -590,7 +592,8 @@
 index_ptr
     Length in bytes from the first byte of the index startcode to the first
     byte of the index_ptr. If there is no index, index_ptr MUST NOT be
-    written.
+    written. If there are several indexes, index_ptr MUST point to the last
+    index.
 
 id
     the ID of the type/name pair, so it is more compact
@@ -692,8 +695,9 @@
 ------
 
 Note: with realtime streaming, there is no end, so no index there either
-An index SHOULD be written for every stream. Indices MUST be placed at end
-of file. Indices MAY be repeated for a stream.
+Index MAY only be repeated after main headers.
+If an index is written anywhere in the file, it MUST be written at end of
+file as well.
 
 
 Info frames:
-------------- next part --------------
--- mpcf.4.txt	2006-02-04 10:14:23.000000000 +0200
+++ mpcf.5.txt	2006-02-04 10:31:46.000000000 +0200
@@ -290,6 +290,7 @@
 
 syncpoint:
     syncpoint_startcode                 f(64)
+    syncpoint_checksum                  u(32)
     coded_pts                           v
     stream = coded_pts % stream_count
     global_key_pts = coded_pts/stream_count
@@ -551,6 +552,11 @@
     including the checksum itself (from first byte after the
     forward_ptr until last byte before the checksum).
 
+syncpoint_checksum
+    adler32 checksum
+    checksum covers from syncpoint timestamp until the end of the frame
+    header immediately following the syncpoint.
+
 back_ptr_div8
     back_ptr = back_ptr_div8 * 8 + 7
     back_ptr must point to a position within 8 bytes of a syncpoint


More information about the MPlayer-dev-eng mailing list