[NUT-devel] Suggestions [PATCH]

Michael Niedermayer michaelni at gmx.at
Tue Feb 28 22:34:22 CET 2006


Hi

the Attached patch does the following:

1. cleanup packets so all have forward_ptr
significantly improves extendability and simplifies stuff
slightly larger overhead (~0.006% which is negligible)


2. split checksum into frame and syncpoint checksum
simplification
overhead changes by + 4byte for every packet >64kb (<0.006% worst case)
overhead changes by - syncpoint size + 4 for every packet with dts_diff > 1sec
overall this could even reduce the overhead, the worst case increase is also
negligible


3. split index
simplification for lavf muxer
    currently we just write the data out seek back and update the forward
    pointer, this is safe as long as the packet is < the io buffer size in
    lavf, if its larger we need to alloc&realloc a buffer and work within that
    or do 2 passes to find the forward ptr value, both are more messy
index_ptr becomes unneccesary by this
improves error resistance


4. always store chapter_start/len
simplification


5. change file structure definion so extendability is restored


6. drop info streams
i see no sense in them ...


7. dissalow width or height == 0


8. add leading coeff to the crc polynom


-- 
Michael
-------------- next part --------------
Index: mpcf.txt
===================================================================
RCS file: /cvsroot/mplayer/main/DOCS/tech/mpcf.txt,v
retrieving revision 1.114
diff -u -r1.114 mpcf.txt
--- mpcf.txt	25 Feb 2006 20:06:21 -0000	1.114
+++ mpcf.txt	28 Feb 2006 20:52:55 -0000
@@ -122,8 +122,6 @@
         Headers:
 
 main header:
-    main_startcode                      f(64)
-    forward_ptr                         v
     version                             v
     stream_count                        v
     max_distance                        v
@@ -162,12 +160,8 @@
             reserved_count[i]= tmp_res;
         }
     }
-    reserved_bytes
-    checksum                            u(32)
 
 stream_header:
-    stream_startcode                    f(64)
-    forward_ptr                         v
     stream_id                           v
     stream_class                        v
     fourcc                              vb
@@ -190,8 +184,6 @@
         samplerate_denom                v
         channel_count                   v
     }
-    reserved_bytes
-    checksum                            u(32)
 
         Basic Packets:
 
@@ -211,22 +203,21 @@
     }
     for(i=0; i<reserved_count[frame_code]; i++)
         reserved                        v
-    if (after_syncpoint){
-        syncpoint_checksum              u(32)
+    if(stream_flags&4){
+        checksum                        u(32)
     }
     data
 
 index:
-    index_startcode                     f(64)
-    forward_ptr                         v
     max_pts                             v
+    syncpoint_start                     v
     syncpoints                          v
-    for(i=0; i<syncpoints; i++){
+    for(i=syncpoint_start; i<syncpoints; i++){
         syncpoint_pos_div8              v
     }
     for(i=0; i<stream_count; i++){
         last_pts= -1
-        for(j=0; j<syncpoints; ){
+        for(j=syncpoint_start; j<syncpoints; ){
             x                           v
             type= x & 1
             x>>=1
@@ -257,17 +248,12 @@
             }
         }
     }
-    reserved_bytes
-    index_ptr                           u(64)
-    checksum                            u(32)
 
-info_frame: (optional)
+info_packet: (optional)
     stream_id_plus1                     v
     chapter_id                          v
-    if (chapter_id) {
-        chapter_start                   v
-        chapter_len                     v
-    }
+    chapter_start                       v
+    chapter_len                         v
     count                               v
     for(i=0; i<count; i++){
         name                            vb
@@ -289,16 +275,8 @@
             type= "v"
         }
     }
-    reserved_bytes
-    checksum                            u(32)
-
-info_packet: (optional)
-    info_startcode                      f(64)
-    forward_ptr                         v
-    info_frame
 
 syncpoint:
-    syncpoint_startcode                 f(64)
     coded_pts                           v
     stream = coded_pts % stream_count
     global_key_pts = coded_pts/stream_count
@@ -309,20 +287,68 @@
 file:
     file_id_string
     while(!eof){
-        main_header
+        if(next_byte == 'N'){
+            startcode                           f(64)
+            forward_ptr                         v
+            switch(startcode){
+                case      main_startcode:  main_header; break;
+                case    stream_startcode:stream_header; break;
+                case      info_startcode:  info_packet; break;
+                case     index_startcode:        index; break;
+                case syncpoint_startcode:    syncpoint; break;
+            }
+            reserved_bytes
+            checksum                    u(32)
+        }else
+            frame
+    }
+
+the structure of a undamaged file should look like the following, but
+demuxers should be flexible and be able to deal with damaged headers so the
+above is a better loop in practice (not to mention its simpler)
+note, demuxers MUST be able to deal with new and unknown headers
+
+prolog
+        startcode                               f(64)
+        forward_ptr                             v
+
+epilog
+        reserved_bytes
+        checksum                                u(32)
+
+reserved_headers
+    while(next_byte == 'N' && next_code !=      main_startcode
+                           && next_code !=    stream_startcode
+                           && next_code !=      info_startcode
+                           && next_code !=     index_startcode
+                           && next_code != syncpoint_startcode){
+        prolog
+        epilog
+    }
+
+file:
+    file_id_string
+    while(!eof){
+        prolog, main_header, epilog
+        reserved_headers
         for(i=0; i<stream_count; i++){
-            stream_header
+            prolog, stream_header, epilog
+            reserved_headers
         }
         while(next_code == info_startcode){
-            info_packet
+            prolog, info_packet, epilog
+            reserved_headers
         }
-        if(next_code == index_startcode){
-            index
+        while(next_code == index_startcode){
+            prolog, index_packet, epilog
+            reserved_headers
         }
         if (!eof) while(next_code != main_startcode){
-            if(next_code == syncpoint_startcode)
-                syncpoint
+            if(next_code == syncpoint_startcode){
+                prolog, syncpoint, epilog
+            }
             frame
+            reserved_headers
         }
     }
 
@@ -386,9 +412,7 @@
     0    video
     1    audio
     2    subtiles
-    3    metadata
     4    userdata
-    in metadata streams each frame contains exactly one info frame
     Note: the remaining values are reserved and MUST NOT be used
           a demuxer MUST ignore streams with reserved classes
 
@@ -476,12 +500,15 @@
       1  is_key             if set, frame is keyframe
       2  end_of_relevance   if set, stream has no relevance on
                             presentation. (EOR)
+      4  has_checksum       if set then the frame header contains a checksum
 
     EOR frames MUST be zero-length and must be set keyframe.
     All streams SHOULD end with EOR, where the pts of the EOR indicates the
     end presentation time of the final frame.
     An EOR set stream is unset by the first content frames.
     EOR can only be unset in streams with zero decode_delay .
+    has_checksum must be set if the frame is larger then 64kb or its
+    dts differs by more then 1 second from the dts of the last frame
 
 stream_id_plus1[frame_code]
     must be <250
@@ -537,7 +564,7 @@
     frames are NOT exempt from this rule)
 
 width/height
-    MUST be set to the coded width/height
+    MUST be set to the coded width/height, MUST not be 0
 
 sample_width/sample_height (aspect ratio)
     sample_width is the horizontal distance between samples
@@ -555,23 +582,17 @@
     the number of samples per second
 
 crc32 checksum
-    Generator polynomial is 0x04C11DB7. Starting value is zero.
+    Generator polynomial is 0x104C11DB7. Starting value is zero.
 
 checksum
     crc32 checksum
     checksum is calculated for the area pointed to by forward_ptr not
     including the checksum itself (from first byte after the
     forward_ptr until last byte before the checksum).
-    In the case of info frames, covers area from begginning of frame.
 
 Syncpoint tags:
 ---------------
 
-syncpoint_checksum
-    crc32 checksum
-    checksum covers from first byte after syncpoint startcode until last
-    byte before the syncpoint_checksum.
-
 back_ptr_div8
     back_ptr = back_ptr_div8 * 8 + 7
     back_ptr must point to a position within 8 bytes of a syncpoint
@@ -613,13 +634,6 @@
     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 of the entire index, from the first byte of the
-    startcode until the last byte of the checksum.
-    Note: A demuxer can use this to find the index when it is written at
-    EOF, as index_ptr will always be 12 bytes before the end of file if
-    there is an index at all.
-
 Info tags:
 ----------
 
@@ -729,21 +743,30 @@
 If an index is written anywhere in the file, it MUST be written at end of
 file as well.
 
+Each index packet SHOULD be <4kb, that way a demuxer can simply:
+for(x=fileend-8192; ; x-=8192){
+    search index startcode
+    if(failure)
+        break;
+    read_index
+}
 
 Info:
 -----
 
-All info packets with the same chapter_id and stream_id are repeated info
-packets and MUST be binary identical.
-
-All info packets MUST appear after main headers at begginning of file, and
-SHOULD be repeated after all main headers unless they are very large.
-
-Info frames can be used to describe the file or some part of it (chapters)
-
-Info SHOULD be stored in global packets instead of info streams/frames if
-possible, and the amount of data is not large.
-
+If 2 info packets have the same chapter_id and stream_id then the earlier
+MUST be ignored (the last info packet is the most correct, this allows
+updating or correcting info)
+
+Info packets MUST be stored and SHOULD be repeated immedeatly after the stream
+headers after all their content becomes known to the muxer
+if they get repeated with every set of stream headers, every set which is
+within their relevance time (chapter_start - end) or just once when they
+become known is a tradeoff between random access and overhead
+if they are small it is strongly recommanded to repeat them with every set of
+stream headers (small here could mean similarely sized to the headers)
+if they are very large or their content is rather unimportant then they 
+SHOULD not be repeated too often
 
 demuxer (non-normative):
 ------------------------


More information about the NUT-devel mailing list