[Ffmpeg-cvslog] r6966 - in trunk/libavformat: Makefile allformats.c nut.h nutdec.c

michael subversion
Sat Nov 11 02:35:51 CET 2006


Author: michael
Date: Sat Nov 11 02:35:50 2006
New Revision: 6966

Added:
   trunk/libavformat/nut.h
   trunk/libavformat/nutdec.c
      - copied, changed from r6963, /trunk/libavformat/nut.c
Modified:
   trunk/libavformat/Makefile
   trunk/libavformat/allformats.c

Log:
updating nut demuxer to latest spec
no muxing yet
no index yet
no seeking yet
libnuts crcs dont match mine (didnt investigate yet)
samplerate is stored wrong by libnut (demuxer has a workaround)
code is not clean or beautifull yet, but i thought its better to commit early before someone unneccesarily wastes his time duplicating the work
demuxer split from muxer


Modified: trunk/libavformat/Makefile
==============================================================================
--- trunk/libavformat/Makefile	(original)
+++ trunk/libavformat/Makefile	Sat Nov 11 02:35:50 2006
@@ -73,8 +73,8 @@
 OBJS-$(CONFIG_MPJPEG_MUXER)              += mpjpeg.o
 OBJS-$(CONFIG_MXF_DEMUXER)               += mxf.o
 OBJS-$(CONFIG_NSV_DEMUXER)               += nsvdec.o riff.o
-OBJS-$(CONFIG_NUT_DEMUXER)               += nut.o riff.o
-OBJS-$(CONFIG_NUT_MUXER)                 += nut.o riff.o
+OBJS-$(CONFIG_NUT_DEMUXER)               += nutdec.o riff.o
+#OBJS-$(CONFIG_NUT_MUXER)                 += nutenc.o riff.o
 OBJS-$(CONFIG_NUV_DEMUXER)               += nuv.o riff.o
 OBJS-$(CONFIG_OGG_DEMUXER)               += ogg2.o           \
                                             oggparsevorbis.o \

Modified: trunk/libavformat/allformats.c
==============================================================================
--- trunk/libavformat/allformats.c	(original)
+++ trunk/libavformat/allformats.c	Sat Nov 11 02:35:50 2006
@@ -249,7 +249,7 @@
     av_register_input_format(&nut_demuxer);
 #endif
 #ifdef CONFIG_NUT_MUXER
-    av_register_output_format(&nut_muxer);
+//    av_register_output_format(&nut_muxer);
 #endif
 #ifdef CONFIG_NUV_DEMUXER
     av_register_input_format(&nuv_demuxer);

Added: trunk/libavformat/nut.h
==============================================================================
--- (empty file)
+++ trunk/libavformat/nut.h	Sat Nov 11 02:35:50 2006
@@ -0,0 +1,94 @@
+/*
+ * "NUT" Container Format (de)muxer
+ * Copyright (c) 2006 Michael Niedermayer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+//#include <limits.h>
+#include "avformat.h"
+#include "crc.h"
+//#include "mpegaudio.h"
+#include "riff.h"
+//#include "adler32.h"
+
+#define      MAIN_STARTCODE (0x7A561F5F04ADULL + (((uint64_t)('N'<<8) + 'M')<<48))
+#define    STREAM_STARTCODE (0x11405BF2F9DBULL + (((uint64_t)('N'<<8) + 'S')<<48))
+#define SYNCPOINT_STARTCODE (0xE4ADEECA4569ULL + (((uint64_t)('N'<<8) + 'K')<<48))
+#define     INDEX_STARTCODE (0xDD672F23E64EULL + (((uint64_t)('N'<<8) + 'X')<<48))
+#define      INFO_STARTCODE (0xAB68B596BA78ULL + (((uint64_t)('N'<<8) + 'I')<<48))
+
+#define ID_STRING "nut/multimedia container\0"
+
+#define MAX_DISTANCE (1024*32-1)
+
+typedef enum{
+    FLAG_KEY        =   1, ///<if set, frame is keyframe
+    FLAG_EOR        =   2, ///<if set, stream has no relevance on presentation. (EOR)
+    FLAG_CODED_PTS  =   8, ///<if set, coded_pts is in the frame header
+    FLAG_STREAM_ID  =  16, ///<if set, stream_id is coded in the frame header
+    FLAG_SIZE_MSB   =  32, ///<if set, data_size_msb is at frame header, otherwise data_size_msb is 0
+    FLAG_CHECKSUM   =  64, ///<if set then the frame header contains a checksum
+    FLAG_RESERVED   = 128, ///<if set, reserved_count is coded in the frame header
+    FLAG_CODED      =4096, ///<if set, coded_flags are stored in the frame header.
+    FLAG_INVALID    =8192, ///<if set, frame_code is invalid.
+}flag_t;
+
+typedef struct {
+    uint32_t pos; //64gb limit if div16 (change this to 64 if thats too little)
+    uint64_t global_key_pts;
+    uint32_t back_ptr_div16; //is stored /16
+} syncpoint_t;
+
+typedef struct {
+    uint16_t flags;
+    uint8_t  stream_id;
+    uint16_t size_mul;
+    uint16_t size_lsb;
+    int16_t  pts_delta;
+    uint8_t  reserved_count;
+} FrameCode; // maybe s/FrameCode/framecode_t/ or change all to java style but dont mix
+
+typedef struct {
+    int last_key_frame;  ///<was the last frame a keyfraeme
+    int64_t last_pts;
+    int time_base_id;
+    AVRational time_base;
+    int msb_pts_shift;
+    int max_pts_distance;
+    int decode_delay; //FIXME duplicate of has_b_frames
+} StreamContext;// maybe s/StreamContext/streamcontext_t/
+
+typedef struct {
+    AVFormatContext *avf;
+//    int written_packet_size;
+//    int64_t packet_start[3]; //0-> startcode less, 1-> short startcode 2-> long startcodes
+    FrameCode frame_code[256];
+    uint64_t next_startcode;     ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable
+    StreamContext *stream;
+    unsigned int max_distance;
+    unsigned int time_base_count;
+    int64_t last_syncpoint_pos;
+    AVRational *time_base;
+} NUTContext;
+
+
+//FIXME move to a common spot, like crc.c/h
+static unsigned long av_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, unsigned int len){
+    return av_crc(av_crc04C11DB7, checksum, buf, len);
+}

Copied: trunk/libavformat/nutdec.c (from r6963, /trunk/libavformat/nut.c)
==============================================================================
--- /trunk/libavformat/nut.c	(original)
+++ trunk/libavformat/nutdec.c	Sat Nov 11 02:35:50 2006
@@ -1,7 +1,7 @@
 /*
- * "NUT" Container Format muxer and demuxer (DRAFT-200403??)
+ * "NUT" Container Format demuxer
+ * Copyright (c) 2004-2006 Michael Niedermayer
  * Copyright (c) 2003 Alex Beregszaszi
- * Copyright (c) 2004 Michael Niedermayer
  *
  * This file is part of FFmpeg.
  *
@@ -19,238 +19,28 @@
  * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  *
- *
- * Visit the official site at http://www.nut.hu/
- *
  */
 
-/*
- * TODO:
- * - index writing
- * - index packet reading support
-*/
-
-//#define DEBUG 1
-
-#include <limits.h>
-#include "avformat.h"
-#include "mpegaudio.h"
-#include "riff.h"
-#include "adler32.h"
+#include "nut.h"
 
 #undef NDEBUG
 #include <assert.h>
 
-//#define TRACE
-
-//from /dev/random
-
-#define     MAIN_STARTCODE (0x7A561F5F04ADULL + (((uint64_t)('N'<<8) + 'M')<<48))
-#define   STREAM_STARTCODE (0x11405BF2F9DBULL + (((uint64_t)('N'<<8) + 'S')<<48))
-#define KEYFRAME_STARTCODE (0xE4ADEECA4569ULL + (((uint64_t)('N'<<8) + 'K')<<48))
-#define    INDEX_STARTCODE (0xDD672F23E64EULL + (((uint64_t)('N'<<8) + 'X')<<48))
-#define     INFO_STARTCODE (0xAB68B596BA78ULL + (((uint64_t)('N'<<8) + 'I')<<48))
-
-#define ID_STRING "nut/multimedia container\0"
-
-#define MAX_DISTANCE (1024*16-1)
-#define MAX_SHORT_DISTANCE (1024*4-1)
-
-#define FLAG_DATA_SIZE       1
-#define FLAG_KEY_FRAME       2
-#define FLAG_INVALID         4
-
-typedef struct {
-    uint8_t flags;
-    uint8_t stream_id_plus1;
-    uint16_t size_mul;
-    uint16_t size_lsb;
-    int16_t timestamp_delta;
-    uint8_t reserved_count;
-} FrameCode;
-
-typedef struct {
-    int last_key_frame;
-    int msb_timestamp_shift;
-    int rate_num;
-    int rate_den;
-    int64_t last_pts;
-    int64_t last_sync_pos;                    ///<pos of last 1/2 type frame
-    int decode_delay;
-} StreamContext;
-
-typedef struct {
-    AVFormatContext *avf;
-    int written_packet_size;
-    int64_t packet_start[3]; //0-> startcode less, 1-> short startcode 2-> long startcodes
-    FrameCode frame_code[256];
-    unsigned int stream_count;
-    uint64_t next_startcode;     ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable
-    StreamContext *stream;
-    int max_distance;
-    int max_short_distance;
-    int rate_num;
-    int rate_den;
-    int short_startcode;
-} NUTContext;
-
-static char *info_table[][2]={
-        {NULL                   ,  NULL }, // end
-        {NULL                   ,  NULL },
-        {NULL                   , "UTF8"},
-        {NULL                   , "v"},
-        {NULL                   , "s"},
-        {"StreamId"             , "v"},
-        {"SegmentId"            , "v"},
-        {"StartTimestamp"       , "v"},
-        {"EndTimestamp"         , "v"},
-        {"Author"               , "UTF8"},
-        {"Title"                , "UTF8"},
-        {"Description"          , "UTF8"},
-        {"Copyright"            , "UTF8"},
-        {"Encoder"              , "UTF8"},
-        {"Keyword"              , "UTF8"},
-        {"Cover"                , "JPEG"},
-        {"Cover"                , "PNG"},
-};
-
-static void update(NUTContext *nut, int stream_index, int64_t frame_start, int frame_type, int frame_code, int key_frame, int size, int64_t pts){
-    StreamContext *stream= &nut->stream[stream_index];
-
-    stream->last_key_frame= key_frame;
-    nut->packet_start[ frame_type ]= frame_start;
-    stream->last_pts= pts;
-}
-
-static void reset(AVFormatContext *s, int64_t global_ts){
-    NUTContext *nut = s->priv_data;
-    int i;
-
-    for(i=0; i<s->nb_streams; i++){
-        StreamContext *stream= &nut->stream[i];
-
-        stream->last_key_frame= 1;
-
-        stream->last_pts= av_rescale(global_ts, stream->rate_num*(int64_t)nut->rate_den, stream->rate_den*(int64_t)nut->rate_num);
-    }
-}
-
-static void build_frame_code(AVFormatContext *s){
-    NUTContext *nut = s->priv_data;
-    int key_frame, index, pred, stream_id;
-    int start=0;
-    int end= 255;
-    int keyframe_0_esc= s->nb_streams > 2;
-    int pred_table[10];
-
-    if(keyframe_0_esc){
-        /* keyframe = 0 escape */
-        FrameCode *ft= &nut->frame_code[start];
-        ft->flags= FLAG_DATA_SIZE;
-        ft->stream_id_plus1= 0;
-        ft->size_mul=1;
-        ft->timestamp_delta=0;
-        start++;
-    }
-
-    for(stream_id= 0; stream_id<s->nb_streams; stream_id++){
-        int start2= start + (end-start)*stream_id / s->nb_streams;
-        int end2  = start + (end-start)*(stream_id+1) / s->nb_streams;
-        AVCodecContext *codec = s->streams[stream_id]->codec;
-        int is_audio= codec->codec_type == CODEC_TYPE_AUDIO;
-        int intra_only= /*codec->intra_only || */is_audio;
-        int pred_count;
-
-        for(key_frame=0; key_frame<2; key_frame++){
-            if(intra_only && keyframe_0_esc && key_frame==0)
-                continue;
-
-            {
-                FrameCode *ft= &nut->frame_code[start2];
-                ft->flags= FLAG_KEY_FRAME*key_frame;
-                ft->flags|= FLAG_DATA_SIZE;
-                ft->stream_id_plus1= stream_id + 1;
-                ft->size_mul=1;
-                ft->timestamp_delta=0;
-                start2++;
-            }
-        }
-
-        key_frame= intra_only;
-#if 1
-        if(is_audio){
-            int frame_bytes= codec->frame_size*(int64_t)codec->bit_rate / (8*codec->sample_rate);
-            int pts;
-            for(pts=0; pts<2; pts++){
-                for(pred=0; pred<2; pred++){
-                    FrameCode *ft= &nut->frame_code[start2];
-                    ft->flags= FLAG_KEY_FRAME*key_frame;
-                    ft->stream_id_plus1= stream_id + 1;
-                    ft->size_mul=frame_bytes + 2;
-                    ft->size_lsb=frame_bytes + pred;
-                    ft->timestamp_delta=pts;
-                    start2++;
-                }
-            }
-        }else{
-            FrameCode *ft= &nut->frame_code[start2];
-            ft->flags= FLAG_KEY_FRAME | FLAG_DATA_SIZE;
-            ft->stream_id_plus1= stream_id + 1;
-            ft->size_mul=1;
-            ft->timestamp_delta=1;
-            start2++;
-        }
-#endif
-
-        if(codec->has_b_frames){
-            pred_count=5;
-            pred_table[0]=-2;
-            pred_table[1]=-1;
-            pred_table[2]=1;
-            pred_table[3]=3;
-            pred_table[4]=4;
-        }else if(codec->codec_id == CODEC_ID_VORBIS){
-            pred_count=3;
-            pred_table[0]=2;
-            pred_table[1]=9;
-            pred_table[2]=16;
-        }else{
-            pred_count=1;
-            pred_table[0]=1;
-        }
-
-        for(pred=0; pred<pred_count; pred++){
-            int start3= start2 + (end2-start2)*pred / pred_count;
-            int end3  = start2 + (end2-start2)*(pred+1) / pred_count;
-
-            for(index=start3; index<end3; index++){
-                FrameCode *ft= &nut->frame_code[index];
-                ft->flags= FLAG_KEY_FRAME*key_frame;
-                ft->flags|= FLAG_DATA_SIZE;
-                ft->stream_id_plus1= stream_id + 1;
-//FIXME use single byte size and pred from last
-                ft->size_mul= end3-start3;
-                ft->size_lsb= index - start3;
-                ft->timestamp_delta= pred_table[pred];
-            }
-        }
-    }
-    memmove(&nut->frame_code['N'+1], &nut->frame_code['N'], sizeof(FrameCode)*(255-'N'));
-    nut->frame_code['N'].flags= FLAG_INVALID;
-}
-
-static uint64_t get_v(ByteIOContext *bc)
-{
+static uint64_t get_v(ByteIOContext *bc/*, maxstuffing*/){
     uint64_t val = 0;
 
     for(;;)
     {
         int tmp = get_byte(bc);
 
+//         if(tmp=0x80){
+//             if(!maxstuffing-- || val)
+//                 return -1;
+//         }
+
         if (tmp&0x80)
             val= (val<<7) + tmp - 0x80;
         else{
-//av_log(NULL, AV_LOG_DEBUG, "get_v()= %"PRId64"\n", (val<<7) + tmp);
             return (val<<7) + tmp;
         }
     }
@@ -283,18 +73,12 @@
     else     return  (v>>1);
 }
 
-static uint64_t get_vb(ByteIOContext *bc){
-    uint64_t val=0;
-    unsigned int i= get_v(bc);
-
-    if(i>8)
-        return UINT64_MAX;
-
-    while(i--)
-        val = (val<<8) + get_byte(bc);
+static uint64_t get_fourcc(ByteIOContext *bc){
+    unsigned int len= get_v(bc);
 
-//av_log(NULL, AV_LOG_DEBUG, "get_vb()= %"PRId64"\n", val);
-    return val;
+    if     (len==2) return get_le16(bc);
+    else if(len==4) return get_le32(bc);
+    else            return -1;
 }
 
 #ifdef TRACE
@@ -323,36 +107,28 @@
 #define get_vb(bc)  get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
 #endif
 
-
 static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int calculate_checksum)
 {
     int64_t start, size;
-    start= url_ftell(bc) - 8;
+//    start= url_ftell(bc) - 8;
 
     size= get_v(bc);
 
-    init_checksum(bc, calculate_checksum ? av_adler32_update : NULL, 1);
+    init_checksum(bc, calculate_checksum ? av_crc04C11DB7_update : NULL, 1);
 
-    nut->packet_start[2] = start;
-    nut->written_packet_size= size;
+//    nut->packet_start[2] = start;
+//    nut->written_packet_size= size;
 
     return size;
 }
 
 static int check_checksum(ByteIOContext *bc){
     unsigned long checksum= get_checksum(bc);
-    return checksum != get_be32(bc);
-}
+//    return checksum != get_be32(bc);
 
-/**
- *
- */
-static int get_length(uint64_t val){
-    int i;
+    av_log(NULL, AV_LOG_ERROR, "%08X %08X\n", checksum, (int)get_be32(bc));
 
-    for (i=7; val>>i; i+=7);
-
-    return i;
+    return 0;
 }
 
 static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
@@ -368,7 +144,7 @@
         switch(state){
         case MAIN_STARTCODE:
         case STREAM_STARTCODE:
-        case KEYFRAME_STARTCODE:
+        case SYNCPOINT_STARTCODE:
         case INFO_STARTCODE:
         case INDEX_STARTCODE:
             return state;
@@ -396,507 +172,81 @@
 }
 
 static int64_t lsb2full(StreamContext *stream, int64_t lsb){
-    int64_t mask = (1<<stream->msb_timestamp_shift)-1;
+    int64_t mask = (1<<stream->msb_pts_shift)-1;
     int64_t delta= stream->last_pts - mask/2;
     return  ((lsb - delta)&mask) + delta;
 }
 
-#ifdef CONFIG_MUXERS
-
-static void put_v(ByteIOContext *bc, uint64_t val)
-{
+static int nut_probe(AVProbeData *p){
     int i;
+    uint64_t code= 0;
 
-//av_log(NULL, AV_LOG_DEBUG, "put_v()= %"PRId64"\n", val);
-    val &= 0x7FFFFFFFFFFFFFFFULL; // FIXME can only encode upto 63 bits currently
-    i= get_length(val);
-
-    for (i-=7; i>0; i-=7){
-        put_byte(bc, 0x80 | (val>>i));
+    for (i = 0; i < p->buf_size; i++) {
+        code = (code << 8) | p->buf[i];
+        if (code == MAIN_STARTCODE)
+            return AVPROBE_SCORE_MAX;
     }
-
-    put_byte(bc, val&0x7f);
-}
-
-/**
- * stores a string as vb.
- */
-static void put_str(ByteIOContext *bc, const char *string){
-    int len= strlen(string);
-
-    put_v(bc, len);
-    put_buffer(bc, string, len);
-}
-
-static void put_s(ByteIOContext *bc, int64_t val){
-    if (val<=0) put_v(bc, -2*val  );
-    else        put_v(bc,  2*val-1);
-}
-
-static void put_vb(ByteIOContext *bc, uint64_t val){
-    int i;
-
-    for (i=8; val>>i; i+=8);
-
-    put_v(bc, i>>3);
-    for(i-=8; i>=0; i-=8)
-        put_byte(bc, (val>>i)&0xFF);
-}
-
-#ifdef TRACE
-static inline void put_v_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){
-    printf("get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
-
-    put_v(bc, v);
-}
-
-static inline void put_s_trace(ByteIOContext *bc, int64_t v, char *file, char *func, int line){
-    printf("get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
-
-    put_s(bc, v);
-}
-
-static inline void put_vb_trace(ByteIOContext *bc, uint64_t v, char *file, char *func, int line){
-    printf("get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
-
-    put_vb(bc, v);
-}
-#define put_v(bc, v)  put_v_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define put_s(bc, v)  put_s_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define put_vb(bc, v)  put_vb_trace(bc, v, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#endif
-
-static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size, int calculate_checksum)
-{
-    put_flush_packet(bc);
-    nut->packet_start[2]= url_ftell(bc) - 8;
-    nut->written_packet_size = max_size;
-
-    /* packet header */
-    put_v(bc, nut->written_packet_size); /* forward ptr */
-
-    if(calculate_checksum)
-        init_checksum(bc, av_adler32_update, 1);
-
     return 0;
 }
 
-/**
- *
- * must not be called more then once per packet
- */
-static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size, int calculate_checksum){
-    int64_t start= nut->packet_start[2];
-    int64_t cur= url_ftell(bc);
-    int size= cur - start - get_length(nut->written_packet_size)/7 - 8;
-
-    if(calculate_checksum)
-        size += 4;
-
-    if(size != nut->written_packet_size){
-        int i;
-
-        assert( size <= nut->written_packet_size );
-
-        url_fseek(bc, start + 8, SEEK_SET);
-        for(i=get_length(size); i < get_length(nut->written_packet_size); i+=7)
-            put_byte(bc, 0x80);
-        put_v(bc, size);
+#define GET_V(dst, check) \
+    tmp= get_v(bc);\
+    if(!(check)){\
+        av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);\
+        return -1;\
+    }\
+    dst= tmp;
 
-        url_fseek(bc, cur, SEEK_SET);
-        nut->written_packet_size= size; //FIXME may fail if multiple updates with differing sizes, as get_length may differ
+static int skip_reserved(ByteIOContext *bc, int64_t pos){
+    pos -= url_ftell(bc);
 
-        if(calculate_checksum)
-            put_be32(bc, get_checksum(bc));
-    }
-
-    return 0;
-}
-
-static int nut_write_header(AVFormatContext *s)
-{
-    NUTContext *nut = s->priv_data;
-    ByteIOContext *bc = &s->pb;
-    AVCodecContext *codec;
-    int i, j, tmp_time, tmp_flags,tmp_stream, tmp_mul, tmp_size, tmp_fields;
-
-    if (strcmp(s->filename, "./data/b-libav.nut")) {
-        av_log(s, AV_LOG_ERROR, " libavformat NUT is non-compliant and disabled\n");
+    if(pos<0){
+        url_fseek(bc, pos, SEEK_CUR);
         return -1;
+    }else{
+        while(pos--)
+            get_byte(bc);
+        return 0;
     }
-
-    nut->avf= s;
-
-    nut->stream =
-        av_mallocz(sizeof(StreamContext)*s->nb_streams);
-
-
-    put_buffer(bc, ID_STRING, strlen(ID_STRING));
-    put_byte(bc, 0);
-    nut->packet_start[2]= url_ftell(bc);
-
-    /* main header */
-    put_be64(bc, MAIN_STARTCODE);
-    put_packetheader(nut, bc, 120+5*256, 1);
-    put_v(bc, 2); /* version */
-    put_v(bc, s->nb_streams);
-    put_v(bc, MAX_DISTANCE);
-    put_v(bc, MAX_SHORT_DISTANCE);
-
-    put_v(bc, nut->rate_num=1);
-    put_v(bc, nut->rate_den=2);
-    put_v(bc, nut->short_startcode=0x4EFE79);
-
-    build_frame_code(s);
-    assert(nut->frame_code['N'].flags == FLAG_INVALID);
-
-    tmp_time= tmp_flags= tmp_stream= tmp_mul= tmp_size= /*tmp_res=*/ INT_MAX;
-    for(i=0; i<256;){
-        tmp_fields=0;
-        tmp_size= 0;
-        if(tmp_time   != nut->frame_code[i].timestamp_delta) tmp_fields=1;
-        if(tmp_mul    != nut->frame_code[i].size_mul       ) tmp_fields=2;
-        if(tmp_stream != nut->frame_code[i].stream_id_plus1) tmp_fields=3;
-        if(tmp_size   != nut->frame_code[i].size_lsb       ) tmp_fields=4;
-//        if(tmp_res    != nut->frame_code[i].res            ) tmp_fields=5;
-
-        tmp_time  = nut->frame_code[i].timestamp_delta;
-        tmp_flags = nut->frame_code[i].flags;
-        tmp_stream= nut->frame_code[i].stream_id_plus1;
-        tmp_mul   = nut->frame_code[i].size_mul;
-        tmp_size  = nut->frame_code[i].size_lsb;
-//        tmp_res   = nut->frame_code[i].res;
-
-        for(j=0; i<256; j++,i++){
-            if(nut->frame_code[i].timestamp_delta != tmp_time  ) break;
-            if(nut->frame_code[i].flags           != tmp_flags ) break;
-            if(nut->frame_code[i].stream_id_plus1 != tmp_stream) break;
-            if(nut->frame_code[i].size_mul        != tmp_mul   ) break;
-            if(nut->frame_code[i].size_lsb        != tmp_size+j) break;
-//            if(nut->frame_code[i].res             != tmp_res   ) break;
-        }
-        if(j != tmp_mul - tmp_size) tmp_fields=6;
-
-        put_v(bc, tmp_flags);
-        put_v(bc, tmp_fields);
-        if(tmp_fields>0) put_s(bc, tmp_time);
-        if(tmp_fields>1) put_v(bc, tmp_mul);
-        if(tmp_fields>2) put_v(bc, tmp_stream);
-        if(tmp_fields>3) put_v(bc, tmp_size);
-        if(tmp_fields>4) put_v(bc, 0 /*tmp_res*/);
-        if(tmp_fields>5) put_v(bc, j);
-    }
-
-    update_packetheader(nut, bc, 0, 1);
-
-    /* stream headers */
-    for (i = 0; i < s->nb_streams; i++)
-    {
-        int nom, denom, ssize;
-
-        codec = s->streams[i]->codec;
-
-        put_be64(bc, STREAM_STARTCODE);
-        put_packetheader(nut, bc, 120 + codec->extradata_size, 1);
-        put_v(bc, i /*s->streams[i]->index*/);
-        switch(codec->codec_type){
-        case CODEC_TYPE_VIDEO: put_v(bc, 0); break;
-        case CODEC_TYPE_AUDIO: put_v(bc, 1); break;
-//        case CODEC_TYPE_TEXT : put_v(bc, 2); break;
-        case CODEC_TYPE_DATA : put_v(bc, 3); break;
-        default: return -1;
-        }
-        if (codec->codec_tag)
-            put_vb(bc, codec->codec_tag);
-        else if (codec->codec_type == CODEC_TYPE_VIDEO)
-        {
-            put_vb(bc, codec_get_bmp_tag(codec->codec_id));
-        }
-        else if (codec->codec_type == CODEC_TYPE_AUDIO)
-        {
-            put_vb(bc, codec_get_wav_tag(codec->codec_id));
-        }
-        else
-            put_vb(bc, 0);
-
-        ff_parse_specific_params(codec, &nom, &ssize, &denom);
-
-        nut->stream[i].rate_num= nom;
-        nut->stream[i].rate_den= denom;
-        av_set_pts_info(s->streams[i], 60, denom, nom);
-
-        put_v(bc, codec->bit_rate);
-        put_vb(bc, 0); /* no language code */
-        put_v(bc, nom);
-        put_v(bc, denom);
-        if(nom / denom < 1000)
-            nut->stream[i].msb_timestamp_shift = 7;
-        else
-            nut->stream[i].msb_timestamp_shift = 14;
-        put_v(bc, nut->stream[i].msb_timestamp_shift);
-        put_v(bc, codec->has_b_frames);
-        put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
-
-        if(codec->extradata_size){
-            put_v(bc, 1);
-            put_v(bc, codec->extradata_size);
-            put_buffer(bc, codec->extradata, codec->extradata_size);
-        }
-        put_v(bc, 0); /* end of codec specific headers */
-
-        switch(codec->codec_type)
-        {
-            case CODEC_TYPE_AUDIO:
-                put_v(bc, codec->sample_rate);
-                put_v(bc, 1);
-                put_v(bc, codec->channels);
-                break;
-            case CODEC_TYPE_VIDEO:
-                put_v(bc, codec->width);
-                put_v(bc, codec->height);
-                put_v(bc, codec->sample_aspect_ratio.num);
-                put_v(bc, codec->sample_aspect_ratio.den);
-                put_v(bc, 0); /* csp type -- unknown */
-                break;
-            default:
-                break;
-        }
-        update_packetheader(nut, bc, 0, 1);
-    }
-
-    /* info header */
-    put_be64(bc, INFO_STARTCODE);
-    put_packetheader(nut, bc, 30+strlen(s->author)+strlen(s->title)+
-        strlen(s->comment)+strlen(s->copyright)+strlen(LIBAVFORMAT_IDENT), 1);
-    if (s->author[0])
-    {
-        put_v(bc, 9); /* type */
-        put_str(bc, s->author);
-    }
-    if (s->title[0])
-    {
-        put_v(bc, 10); /* type */
-        put_str(bc, s->title);
-    }
-    if (s->comment[0])
-    {
-        put_v(bc, 11); /* type */
-        put_str(bc, s->comment);
-    }
-    if (s->copyright[0])
-    {
-        put_v(bc, 12); /* type */
-        put_str(bc, s->copyright);
-    }
-    /* encoder */
-    if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)){
-        put_v(bc, 13); /* type */
-        put_str(bc, LIBAVFORMAT_IDENT);
-    }
-
-    put_v(bc, 0); /* eof info */
-    update_packetheader(nut, bc, 0, 1);
-
-    put_flush_packet(bc);
-
-    return 0;
-}
-
-static int nut_write_packet(AVFormatContext *s, AVPacket *pkt)
-{
-    NUTContext *nut = s->priv_data;
-    StreamContext *stream= &nut->stream[pkt->stream_index];
-    ByteIOContext *bc = &s->pb;
-    int key_frame = 0, full_pts=0;
-    AVCodecContext *enc;
-    int64_t coded_pts;
-    int frame_type, best_length, frame_code, flags, i, size_mul, size_lsb, time_delta;
-    const int64_t frame_start= url_ftell(bc);
-    int64_t pts= pkt->pts;
-    int size= pkt->size;
-    int stream_index= pkt->stream_index;
-
-    enc = s->streams[stream_index]->codec;
-    key_frame = !!(pkt->flags & PKT_FLAG_KEY);
-
-    frame_type=0;
-    if(frame_start + size + 20 - FFMAX(nut->packet_start[1], nut->packet_start[2]) > MAX_DISTANCE)
-        frame_type=2;
-    if(key_frame && !stream->last_key_frame)
-        frame_type=2;
-
-    if(frame_type>1){
-        int64_t global_ts= av_rescale(pts, stream->rate_den*(int64_t)nut->rate_num, stream->rate_num*(int64_t)nut->rate_den);
-        reset(s, global_ts);
-        put_be64(bc, KEYFRAME_STARTCODE);
-        put_v(bc, global_ts);
-    }
-    assert(stream->last_pts != AV_NOPTS_VALUE);
-    coded_pts = pts & ((1<<stream->msb_timestamp_shift)-1);
-    if(lsb2full(stream, coded_pts) != pts)
-        full_pts=1;
-
-    if(full_pts)
-        coded_pts= pts + (1<<stream->msb_timestamp_shift);
-
-    best_length=INT_MAX;
-    frame_code= -1;
-    for(i=0; i<256; i++){
-        int stream_id_plus1= nut->frame_code[i].stream_id_plus1;
-        int fc_key_frame;
-        int length=0;
-        size_mul= nut->frame_code[i].size_mul;
-        size_lsb= nut->frame_code[i].size_lsb;
-        time_delta= nut->frame_code[i].timestamp_delta;
-        flags= nut->frame_code[i].flags;
-
-        assert(size_mul > size_lsb);
-
-        if(stream_id_plus1 == 0) length+= get_length(stream_index);
-        else if(stream_id_plus1 - 1 != stream_index)
-            continue;
-        fc_key_frame= !!(flags & FLAG_KEY_FRAME);
-
-        assert(key_frame==0 || key_frame==1);
-        if(fc_key_frame != key_frame)
-            continue;
-
-        if(flags & FLAG_DATA_SIZE){
-            if(size % size_mul != size_lsb)
-                continue;
-            length += get_length(size / size_mul);
-        }else if(size != size_lsb)
-            continue;
-
-        if(full_pts && time_delta)
-            continue;
-
-        if(!time_delta){
-            length += get_length(coded_pts);
-        }else{
-            if(time_delta != pts - stream->last_pts)
-                continue;
-        }
-
-        if(length < best_length){
-            best_length= length;
-            frame_code=i;
-        }
-//    av_log(s, AV_LOG_DEBUG, "%d %d %d %d %d %d %d %d %d %d\n", key_frame, frame_type, full_pts, size, stream_index, flags, size_mul, size_lsb, stream_id_plus1, length);
-    }
-
-    assert(frame_code != -1);
-    flags= nut->frame_code[frame_code].flags;
-    size_mul= nut->frame_code[frame_code].size_mul;
-    size_lsb= nut->frame_code[frame_code].size_lsb;
-    time_delta= nut->frame_code[frame_code].timestamp_delta;
-#ifdef TRACE
-    best_length /= 7;
-    best_length ++; //frame_code
-    if(frame_type==2){
-        best_length += 8; // startcode
-    }
-    av_log(s, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d size:%d stream:%d flag:%d mul:%d lsb:%d s+1:%d pts_delta:%d pts:%"PRId64" fs:%"PRId64"\n", key_frame, frame_type, full_pts ? 1 : 0, frame_code, best_length, size, stream_index, flags, size_mul, size_lsb, nut->frame_code[frame_code].stream_id_plus1,(int)(pts - stream->last_pts), pts, frame_start);
-//    av_log(s, AV_LOG_DEBUG, "%d %d %d\n", stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);
-#endif
-
-    assert(frame_type != 1); //short startcode not implemented yet
-    put_byte(bc, frame_code);
-
-    if(nut->frame_code[frame_code].stream_id_plus1 == 0)
-        put_v(bc, stream_index);
-    if (!time_delta){
-        put_v(bc, coded_pts);
-    }
-    if(flags & FLAG_DATA_SIZE)
-        put_v(bc, size / size_mul);
-    else
-        assert(size == size_lsb);
-    if(size > MAX_DISTANCE){
-        assert(frame_type > 1);
-    }
-
-    put_buffer(bc, pkt->data, size);
-
-    update(nut, stream_index, frame_start, frame_type, frame_code, key_frame, size, pts);
-
-    return 0;
-}
-
-static int nut_write_trailer(AVFormatContext *s)
-{
-    NUTContext *nut = s->priv_data;
-    ByteIOContext *bc = &s->pb;
-
-#if 0
-    int i;
-
-    /* WRITE INDEX */
-
-    for (i = 0; s->nb_streams; i++)
-    {
-        put_be64(bc, INDEX_STARTCODE);
-        put_packetheader(nut, bc, 64, 1);
-        put_v(bc, s->streams[i]->id);
-        put_v(bc, ...);
-        update_packetheader(nut, bc, 0, 1);
-    }
-#endif
-
-    put_flush_packet(bc);
-
-    av_freep(&nut->stream);
-
-    return 0;
-}
-#endif //CONFIG_MUXERS
-
-static int nut_probe(AVProbeData *p)
-{
-    int i;
-    uint64_t code= 0xff;
-
-    for (i = 0; i < p->buf_size; i++) {
-        code = (code << 8) | p->buf[i];
-        if (code == MAIN_STARTCODE)
-            return AVPROBE_SCORE_MAX;
-    }
-    return 0;
 }
 
 static int decode_main_header(NUTContext *nut){
     AVFormatContext *s= nut->avf;
     ByteIOContext *bc = &s->pb;
-    uint64_t tmp;
-    int i, j, tmp_stream, tmp_mul, tmp_time, tmp_size, count, tmp_res;
+    uint64_t tmp, end;
+    unsigned int stream_count;
+    int i, j, tmp_stream, tmp_mul, tmp_pts, tmp_size, count, tmp_res;
 
-    get_packetheader(nut, bc, 1);
+    end= get_packetheader(nut, bc, 1);
+    end += url_ftell(bc) - 4;
 
-    tmp = get_v(bc);
-    if (tmp != 2){
-        av_log(s, AV_LOG_ERROR, "bad version (%"PRId64")\n", tmp);
-        return -1;
-    }
+    GET_V(tmp              , tmp >=2 && tmp <= 3)
+    GET_V(stream_count     , tmp > 0 && tmp <=MAX_STREAMS)
 
-    nut->stream_count = get_v(bc);
-    if(nut->stream_count > MAX_STREAMS){
-        av_log(s, AV_LOG_ERROR, "too many streams\n");
-        return -1;
-    }
     nut->max_distance = get_v(bc);
-    nut->max_short_distance = get_v(bc);
-    nut->rate_num= get_v(bc);
-    nut->rate_den= get_v(bc);
-    nut->short_startcode= get_v(bc);
-    if(nut->short_startcode>>16 != 'N'){
-        av_log(s, AV_LOG_ERROR, "invalid short startcode %X\n", nut->short_startcode);
-        return -1;
+    if(nut->max_distance > 65536){
+        av_log(s, AV_LOG_DEBUG, "max_distance %d\n", nut->max_distance);
+        nut->max_distance= 65536;
     }
 
+    GET_V(nut->time_base_count, tmp>0 && tmp<INT_MAX / sizeof(AVRational))
+    nut->time_base= av_malloc(nut->time_base_count * sizeof(AVRational));
+
+    for(i=0; i<nut->time_base_count; i++){
+        GET_V(nut->time_base[i].num, tmp>0 && tmp<(1ULL<<31))
+        GET_V(nut->time_base[i].den, tmp>0 && tmp<(1ULL<<31))
+        if(ff_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1){
+            av_log(s, AV_LOG_ERROR, "time base invalid\n");
+            return -1;
+        }
+    }
+    tmp_pts=0;
+    tmp_mul=1;
+    tmp_stream=0;
     for(i=0; i<256;){
         int tmp_flags = get_v(bc);
         int tmp_fields= get_v(bc);
-        if(tmp_fields>0) tmp_time  = get_s(bc);
+        if(tmp_fields>0) tmp_pts   = get_s(bc);
         if(tmp_fields>1) tmp_mul   = get_v(bc);
         if(tmp_fields>2) tmp_stream= get_v(bc);
         if(tmp_fields>3) tmp_size  = get_v(bc);
@@ -913,51 +263,60 @@
             av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
             return -1;
         }
-        if(tmp_stream > nut->stream_count + 1){
+        if(tmp_stream >= stream_count){
             av_log(s, AV_LOG_ERROR, "illegal stream number\n");
             return -1;
         }
 
         for(j=0; j<count; j++,i++){
+            if (i == 'N') {
+                nut->frame_code[i].flags= FLAG_INVALID;
+                j--;
+                continue;
+            }
             nut->frame_code[i].flags           = tmp_flags ;
-            nut->frame_code[i].timestamp_delta = tmp_time  ;
-            nut->frame_code[i].stream_id_plus1 = tmp_stream;
+            nut->frame_code[i].pts_delta       = tmp_pts   ;
+            nut->frame_code[i].stream_id       = tmp_stream;
             nut->frame_code[i].size_mul        = tmp_mul   ;
             nut->frame_code[i].size_lsb        = tmp_size+j;
             nut->frame_code[i].reserved_count  = tmp_res   ;
         }
     }
-    if(nut->frame_code['N'].flags != FLAG_INVALID){
-        av_log(s, AV_LOG_ERROR, "illegal frame_code table\n");
-        return -1;
-    }
+    assert(nut->frame_code['N'].flags == FLAG_INVALID);
 
-    if(check_checksum(bc)){
+    if(skip_reserved(bc, end) || check_checksum(bc)){
         av_log(s, AV_LOG_ERROR, "Main header checksum mismatch\n");
         return -1;
     }
 
+    nut->stream = av_mallocz(sizeof(StreamContext)*stream_count);
+    for(i=0; i<stream_count; i++){
+        av_new_stream(s, i);
+    }
+
     return 0;
 }
 
 static int decode_stream_header(NUTContext *nut){
     AVFormatContext *s= nut->avf;
     ByteIOContext *bc = &s->pb;
+    StreamContext *stc;
     int class, nom, denom, stream_id;
-    uint64_t tmp;
+    uint64_t tmp, end;
     AVStream *st;
 
-    get_packetheader(nut, bc, 1);
-    stream_id= get_v(bc);
-    if(stream_id >= nut->stream_count || s->streams[stream_id])
-        return -1;
+    end= get_packetheader(nut, bc, 1);
+    end += url_ftell(bc) - 4;
+
+    GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base.num);
+    stc= &nut->stream[stream_id];
 
-    st = av_new_stream(s, stream_id);
+    st = s->streams[stream_id];
     if (!st)
         return AVERROR_NOMEM;
 
     class = get_v(bc);
-    tmp = get_vb(bc);
+    tmp = get_fourcc(bc);
     st->codec->codec_tag= tmp;
     switch(class)
     {
@@ -968,7 +327,6 @@
                 av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
             break;
         case 1:
-        case 32: //compatibility
             st->codec->codec_type = CODEC_TYPE_AUDIO;
             st->codec->codec_id = codec_get_wav_id(tmp);
             if (st->codec->codec_id == CODEC_ID_NONE)
@@ -984,95 +342,129 @@
             av_log(s, AV_LOG_ERROR, "Unknown stream class (%d)\n", class);
             return -1;
     }
-    s->bit_rate += get_v(bc);
-    get_vb(bc); /* language code */
-    nom = get_v(bc);
-    denom = get_v(bc);
-    nut->stream[stream_id].msb_timestamp_shift = get_v(bc);
-    st->codec->has_b_frames=
-    nut->stream[stream_id].decode_delay= get_v(bc);
-    get_byte(bc); /* flags */
-
-    /* codec specific data headers */
-    while(get_v(bc) != 0){
-        st->codec->extradata_size= get_v(bc);
-        if((unsigned)st->codec->extradata_size > (1<<30))
-            return -1;
+    GET_V(stc->time_base_id    , tmp < nut->time_base_count);
+    GET_V(stc->msb_pts_shift   , tmp < 16);
+    stc->max_pts_distance= get_v(bc);
+    GET_V(stc->decode_delay    , tmp < 1000); //sanity limit, raise this if moors law is true
+    st->codec->has_b_frames= stc->decode_delay;
+    get_v(bc); //stream flags
+
+    GET_V(st->codec->extradata_size, tmp < (1<<30));
+    if(st->codec->extradata_size){
         st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
         get_buffer(bc, st->codec->extradata, st->codec->extradata_size);
-//            url_fskip(bc, get_v(bc));
     }
 
-    if (st->codec->codec_type == CODEC_TYPE_VIDEO) /* VIDEO */
-    {
-        st->codec->width = get_v(bc);
-        st->codec->height = get_v(bc);
+    if (st->codec->codec_type == CODEC_TYPE_VIDEO){
+        GET_V(st->codec->width , tmp > 0)
+        GET_V(st->codec->height, tmp > 0)
         st->codec->sample_aspect_ratio.num= get_v(bc);
         st->codec->sample_aspect_ratio.den= get_v(bc);
+        if((!st->codec->sample_aspect_ratio.num) != (!st->codec->sample_aspect_ratio.den)){
+            av_log(s, AV_LOG_ERROR, "invalid aspect ratio\n");
+            return -1;
+        }
         get_v(bc); /* csp type */
+    }else if (st->codec->codec_type == CODEC_TYPE_AUDIO){
+        GET_V(st->codec->sample_rate , tmp > 0)
+        tmp= get_v(bc); // samplerate_den
+        if(tmp > st->codec->sample_rate){
+            av_log(s, AV_LOG_ERROR, "bleh, libnut muxed this ;)\n");
+            st->codec->sample_rate= tmp;
+        }
+        GET_V(st->codec->channels, tmp > 0)
     }
-    if (st->codec->codec_type == CODEC_TYPE_AUDIO) /* AUDIO */
-    {
-        st->codec->sample_rate = get_v(bc);
-        get_v(bc); // samplerate_den
-        st->codec->channels = get_v(bc);
-    }
-    if(check_checksum(bc)){
+    if(skip_reserved(bc, end) || check_checksum(bc)){
         av_log(s, AV_LOG_ERROR, "Stream header %d checksum mismatch\n", stream_id);
         return -1;
     }
-    av_set_pts_info(s->streams[stream_id], 60, denom, nom);
-    nut->stream[stream_id].rate_num= nom;
-    nut->stream[stream_id].rate_den= denom;
+    stc->time_base= nut->time_base[stc->time_base_id];
+    av_set_pts_info(s->streams[stream_id], 63, stc->time_base.num, stc->time_base.den);
     return 0;
 }
 
 static int decode_info_header(NUTContext *nut){
     AVFormatContext *s= nut->avf;
     ByteIOContext *bc = &s->pb;
-
-    get_packetheader(nut, bc, 1);
-
-    for(;;){
-        int id= get_v(bc);
-        char *name, *type, custom_name[256], custom_type[256];
-
-        if(!id)
-            break;
-        else if(id >= sizeof(info_table)/sizeof(info_table[0])){
-            av_log(s, AV_LOG_ERROR, "info id is too large %d %zd\n", id, sizeof(info_table)/sizeof(info_table[0]));
-            return -1;
-        }
-
-        type= info_table[id][1];
-        name= info_table[id][0];
-//av_log(s, AV_LOG_DEBUG, "%d %s %s\n", id, type, name);
-
-        if(!type){
-            get_str(bc, custom_type, sizeof(custom_type));
-            type= custom_type;
-        }
-        if(!name){
-            get_str(bc, custom_name, sizeof(custom_name));
-            name= custom_name;
+    uint64_t tmp;
+    unsigned int stream_id_plus1, chapter_start, chapter_len, count;
+    int chapter_id, i;
+    int64_t value, end;
+    char name[256], str_value[1024], type_str[256], *type= type_str;
+
+    end= get_packetheader(nut, bc, 1);
+    end += url_ftell(bc) - 4;
+
+    GET_V(stream_id_plus1, tmp <= s->nb_streams)
+    chapter_id   = get_s(bc);
+    chapter_start= get_v(bc);
+    chapter_len  = get_v(bc);
+    count        = get_v(bc);
+    for(i=0; i<count; i++){
+        get_str(bc, name, sizeof(name));
+        value= get_s(bc);
+        if(value == -1){
+            type= "UTF-8";
+            get_str(bc, str_value, sizeof(str_value));
+        }else if(value == -2){
+            get_str(bc, type, sizeof(type));
+            get_str(bc, str_value, sizeof(str_value));
+        }else if(value == -3){
+            type= "s";
+            value= get_s(bc);
+        }else if(value == -4){
+            type= "t";
+            value= get_v(bc);
+        }else if(value < -4){
+            type= "r";
+            get_s(bc);
+        }else{
+            type= "v";
         }
 
-        if(!strcmp(type, "v")){
-            get_v(bc);
-        }else{
-            if(!strcmp(name, "Author"))
-                get_str(bc, s->author, sizeof(s->author));
+        if(chapter_id==0 && !strcmp(type, "UTF-8")){
+            if     (!strcmp(name, "Author"))
+                pstrcpy(s->author   , sizeof(s->author)   , str_value);
             else if(!strcmp(name, "Title"))
-                get_str(bc, s->title, sizeof(s->title));
+                pstrcpy(s->title    , sizeof(s->title)    , str_value);
             else if(!strcmp(name, "Copyright"))
-                get_str(bc, s->copyright, sizeof(s->copyright));
+                pstrcpy(s->copyright, sizeof(s->copyright), str_value);
             else if(!strcmp(name, "Description"))
-                get_str(bc, s->comment, sizeof(s->comment));
-            else
-                get_str(bc, NULL, 0);
+                pstrcpy(s->comment  , sizeof(s->comment)  , str_value);
         }
     }
-    if(check_checksum(bc)){
+
+    if(skip_reserved(bc, end) || check_checksum(bc)){
+        av_log(s, AV_LOG_ERROR, "Info header checksum mismatch\n");
+        return -1;
+    }
+    return 0;
+}
+
+static int decode_syncpoint(NUTContext *nut){
+    AVFormatContext *s= nut->avf;
+    ByteIOContext *bc = &s->pb;
+    int64_t end;
+    uint64_t tmp;
+    int i;
+    AVRational time_base;
+
+    nut->last_syncpoint_pos= url_ftell(bc);
+
+    end= get_packetheader(nut, bc, 1);
+    end += url_ftell(bc) - 4;
+
+    tmp= get_v(bc);
+    get_v(bc); //back_ptr_div16
+
+    time_base= nut->time_base[tmp % nut->time_base_count];
+    for(i=0; i<s->nb_streams; i++){
+        nut->stream[i].last_pts= av_rescale_q(tmp / nut->time_base_count, time_base, nut->stream[i].time_base); //FIXME rounding and co
+        //last_key_frame ?
+    }
+    //FIXME put this in a reset func maybe
+
+    if(skip_reserved(bc, end) || check_checksum(bc)){
         av_log(s, AV_LOG_ERROR, "Info header checksum mismatch\n");
         return -1;
     }
@@ -1092,7 +484,7 @@
     pos=0;
     for(;;){
         pos= find_startcode(bc, MAIN_STARTCODE, pos)+1;
-        if (pos<0){
+        if (pos<0+1){
             av_log(s, AV_LOG_ERROR, "no main startcode found\n");
             return -1;
         }
@@ -1100,14 +492,9 @@
             break;
     }
 
-
-    s->bit_rate = 0;
-
-    nut->stream = av_malloc(sizeof(StreamContext)*nut->stream_count);
-
     /* stream headers */
     pos=0;
-    for(inited_stream_count=0; inited_stream_count < nut->stream_count;){
+    for(inited_stream_count=0; inited_stream_count < s->nb_streams;){
         pos= find_startcode(bc, STREAM_STARTCODE, pos)+1;
         if (pos<0+1){
             av_log(s, AV_LOG_ERROR, "not all stream headers found\n");
@@ -1126,7 +513,7 @@
         if(startcode==0){
             av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
             return -1;
-        }else if(startcode == KEYFRAME_STARTCODE){
+        }else if(startcode == SYNCPOINT_STARTCODE){
             nut->next_startcode= startcode;
             break;
         }else if(startcode != INFO_STARTCODE){
@@ -1139,107 +526,73 @@
     return 0;
 }
 
-static int decode_frame_header(NUTContext *nut, int *key_frame_ret, int64_t *pts_ret, int *stream_id_ret, int frame_code, int frame_type, int64_t frame_start){
+static int decode_frame_header(NUTContext *nut, int *flags_ret, int64_t *pts, int *stream_id, int frame_code){
     AVFormatContext *s= nut->avf;
-    StreamContext *stream;
     ByteIOContext *bc = &s->pb;
-    int size, flags, size_mul, size_lsb, stream_id, time_delta;
-    int64_t pts = 0;
+    StreamContext *stc;
+    int size, flags, size_mul, pts_delta, i, reserved_count;
+    uint64_t tmp;
 
-    if(frame_type < 2 && frame_start - nut->packet_start[2] > nut->max_distance){
+    if(url_ftell(bc) > nut->last_syncpoint_pos + nut->max_distance){
         av_log(s, AV_LOG_ERROR, "last frame must have been damaged\n");
         return -1;
     }
 
-    if(frame_type)
-        nut->packet_start[ frame_type ]= frame_start; //otherwise 1 goto 1 may happen
-
-    flags= nut->frame_code[frame_code].flags;
-    size_mul= nut->frame_code[frame_code].size_mul;
-    size_lsb= nut->frame_code[frame_code].size_lsb;
-    stream_id= nut->frame_code[frame_code].stream_id_plus1 - 1;
-    time_delta= nut->frame_code[frame_code].timestamp_delta;
-
-    if(stream_id==-1)
-        stream_id= get_v(bc);
-    if(stream_id >= s->nb_streams){
-        av_log(s, AV_LOG_ERROR, "illegal stream_id\n");
-        return -1;
-    }
-    stream= &nut->stream[stream_id];
-
-//    av_log(s, AV_LOG_DEBUG, "ft:%d ppts:%d %d %d\n", frame_type, stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);
-
-    *key_frame_ret= !!(flags & FLAG_KEY_FRAME);
-
-    if(!time_delta){
-        int64_t mask = (1<<stream->msb_timestamp_shift)-1;
-        pts= get_v(bc);
-        if(pts > mask){
-            pts -= mask+1;
-        }else{
-            if(stream->last_pts == AV_NOPTS_VALUE){
-                av_log(s, AV_LOG_ERROR, "no reference pts available\n");
-                return -1;
-            }
-            pts= lsb2full(stream, pts);
-        }
-    }else{
-        if(stream->last_pts == AV_NOPTS_VALUE){
-            av_log(s, AV_LOG_ERROR, "no reference pts available\n");
-            return -1;
-        }
-        pts= stream->last_pts + time_delta;
-    }
-
-    if(*key_frame_ret){
-//        av_log(s, AV_LOG_DEBUG, "stream:%d start:%"PRId64" pts:%"PRId64" length:%"PRId64"\n",stream_id, frame_start, av_pts, frame_start - nut->stream[stream_id].last_sync_pos);
-        av_add_index_entry(
-            s->streams[stream_id],
-            frame_start,
-            pts,
-            0,
-            frame_start - nut->stream[stream_id].last_sync_pos,
-            AVINDEX_KEYFRAME);
-        nut->stream[stream_id].last_sync_pos= frame_start;
-//                assert(nut->packet_start == frame_start);
-    }
-
-    assert(size_mul > size_lsb);
-    size= size_lsb;
-    if(flags & FLAG_DATA_SIZE)
-        size+= size_mul*get_v(bc);
-
-#ifdef TRACE
-av_log(s, AV_LOG_DEBUG, "fs:%"PRId64" fc:%d ft:%d kf:%d pts:%"PRId64" size:%d mul:%d lsb:%d flags:%d delta:%d\n", frame_start, frame_code, frame_type, *key_frame_ret, pts, size, size_mul, size_lsb, flags, time_delta);
-#endif
-
-    if(frame_type==0 && url_ftell(bc) - nut->packet_start[2] + size > nut->max_distance){
-        av_log(s, AV_LOG_ERROR, "frame size too large\n");
-        return -1;
+    flags          = nut->frame_code[frame_code].flags;
+    size_mul       = nut->frame_code[frame_code].size_mul;
+    size           = nut->frame_code[frame_code].size_lsb;
+    *stream_id     = nut->frame_code[frame_code].stream_id;
+    pts_delta      = nut->frame_code[frame_code].pts_delta;
+    reserved_count = nut->frame_code[frame_code].reserved_count;
+
+    if(flags & FLAG_INVALID)
+        return -1;
+    if(flags & FLAG_CODED)
+        flags ^= get_v(bc);
+    if(flags & FLAG_STREAM_ID){
+        GET_V(*stream_id, tmp < s->nb_streams)
+    }
+    stc= &nut->stream[*stream_id];
+    if(flags&FLAG_CODED_PTS){
+        int coded_pts= get_v(bc);
+//FIXME check last_pts validity?
+        if(coded_pts < (1<<stc->msb_pts_shift)){
+            *pts=lsb2full(stc, coded_pts);
+        }else
+            *pts=coded_pts - (1<<stc->msb_pts_shift);
+    }else
+        *pts= stc->last_pts + pts_delta;
+    if(flags&FLAG_SIZE_MSB){
+        size += size_mul*get_v(bc);
+    }
+    if(flags&FLAG_RESERVED)
+        reserved_count= get_v(bc);
+    for(i=0; i<reserved_count; i++)
+        get_v(bc);
+    if(flags&FLAG_CHECKSUM){
+        get_be32(bc); //FIXME check this
     }
+    *flags_ret= flags;
 
-    *stream_id_ret = stream_id;
-    *pts_ret = pts;
-
-    update(nut, stream_id, frame_start, frame_type, frame_code, *key_frame_ret, size, pts);
+    stc->last_pts= *pts;
+    stc->last_key_frame= flags&FLAG_KEY; //FIXME change to last flags
 
     return size;
 }
 
-static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code, int frame_type, int64_t frame_start){
+static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code){
     AVFormatContext *s= nut->avf;
     ByteIOContext *bc = &s->pb;
-    int size, stream_id, key_frame, discard;
+    int size, stream_id, flags, discard;
     int64_t pts, last_IP_pts;
 
-    size= decode_frame_header(nut, &key_frame, &pts, &stream_id, frame_code, frame_type, frame_start);
+    size= decode_frame_header(nut, &flags, &pts, &stream_id, frame_code);
     if(size < 0)
         return -1;
 
     discard= s->streams[ stream_id ]->discard;
     last_IP_pts= s->streams[ stream_id ]->last_IP_pts;
-    if(  (discard >= AVDISCARD_NONKEY && !key_frame)
+    if(  (discard >= AVDISCARD_NONKEY && !(flags & FLAG_KEY))
        ||(discard >= AVDISCARD_BIDIR && last_IP_pts != AV_NOPTS_VALUE && last_IP_pts > pts)
        || discard >= AVDISCARD_ALL){
         url_fskip(bc, size);
@@ -1248,7 +601,7 @@
 
     av_get_packet(bc, pkt, size);
     pkt->stream_index = stream_id;
-    if (key_frame)
+    if (flags & FLAG_KEY)
         pkt->flags |= PKT_FLAG_KEY;
     pkt->pts = pts;
 
@@ -1259,11 +612,10 @@
 {
     NUTContext *nut = s->priv_data;
     ByteIOContext *bc = &s->pb;
-    int i, frame_code=0, ret;
+    int i, frame_code=0, ret, skip;
 
     for(;;){
         int64_t pos= url_ftell(bc);
-        int frame_type= 0;
         uint64_t tmp= nut->next_startcode;
         nut->next_startcode=0;
 
@@ -1284,28 +636,27 @@
         case MAIN_STARTCODE:
         case STREAM_STARTCODE:
         case INDEX_STARTCODE:
-            get_packetheader(nut, bc, 0);
-            assert(nut->packet_start[2] == pos);
-            url_fseek(bc, nut->written_packet_size, SEEK_CUR);
+            skip= get_packetheader(nut, bc, 0);
+            url_fseek(bc, skip, SEEK_CUR);
             break;
         case INFO_STARTCODE:
             if(decode_info_header(nut)<0)
                 goto resync;
             break;
-        case KEYFRAME_STARTCODE:
-            frame_type = 2;
-            reset(s, get_v(bc));
+        case SYNCPOINT_STARTCODE:
+            if(decode_syncpoint(nut)<0)
+                goto resync;
             frame_code = get_byte(bc);
         case 0:
-            ret= decode_frame(nut, pkt, frame_code, frame_type, pos);
+            ret= decode_frame(nut, pkt, frame_code);
             if(ret==0)
                 return 0;
             else if(ret==1) //ok but discard packet
                 break;
         default:
 resync:
-av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", nut->packet_start[2]+1);
-            tmp= find_any_startcode(bc, nut->packet_start[2]+1);
+av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", pos);
+            tmp= find_any_startcode(bc, pos+1);
             if(tmp==0)
                 return -1;
 av_log(s, AV_LOG_DEBUG, "sync\n");
@@ -1314,107 +665,11 @@
     }
 }
 
-static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){
-    NUTContext *nut = s->priv_data;
-    StreamContext *stream;
-    ByteIOContext *bc = &s->pb;
-    int64_t pos, pts;
-    uint64_t code;
-    int frame_code,step, stream_id, i,size, key_frame;
-av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n", stream_index, *pos_arg, pos_limit);
-
-    if(*pos_arg < 0)
-        return AV_NOPTS_VALUE;
-
-    pos= *pos_arg;
-    step= FFMIN(16*1024, pos);
-    do{
-        pos-= step;
-        code= find_any_startcode(bc, pos);
-
-        if(code && url_ftell(bc) - 8 <= *pos_arg)
-            break;
-        step= FFMIN(2*step, pos);
-    }while(step);
-
-    if(!code) //nothing found, not even after pos_arg
-        return AV_NOPTS_VALUE;
-
-    url_fseek(bc, -8, SEEK_CUR);
-    for(i=0; i<s->nb_streams; i++)
-        nut->stream[i].last_sync_pos= url_ftell(bc);
-
-    for(;;){
-        int frame_type=0;
-        int64_t pos= url_ftell(bc);
-        uint64_t tmp=0;
-
-        if(pos > pos_limit || url_feof(bc))
-            return AV_NOPTS_VALUE;
-
-        frame_code = get_byte(bc);
-        if(frame_code == 'N'){
-            tmp= frame_code;
-            for(i=1; i<8; i++)
-                tmp = (tmp<<8) + get_byte(bc);
-        }
-//av_log(s, AV_LOG_DEBUG, "before switch %"PRIX64" at=%"PRId64"\n", tmp, pos);
-
-        switch(tmp){
-        case MAIN_STARTCODE:
-        case STREAM_STARTCODE:
-        case INDEX_STARTCODE:
-        case INFO_STARTCODE:
-            get_packetheader(nut, bc, 0);
-            assert(nut->packet_start[2]==pos);
-            url_fseek(bc, nut->written_packet_size, SEEK_CUR);
-            break;
-        case KEYFRAME_STARTCODE:
-            frame_type=2;
-            reset(s, get_v(bc));
-            frame_code = get_byte(bc);
-        case 0:
-            size= decode_frame_header(nut, &key_frame, &pts, &stream_id, frame_code, frame_type, pos);
-            if(size < 0)
-                goto resync;
-
-            stream= &nut->stream[stream_id];
-            if(stream_id != stream_index || !key_frame || pos < *pos_arg){
-                url_fseek(bc, size, SEEK_CUR);
-                break;
-            }
-
-            *pos_arg= pos;
-            return pts;
-        default:
-resync:
-av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", nut->packet_start[2]+1);
-            if(!find_any_startcode(bc, nut->packet_start[2]+1))
-                return AV_NOPTS_VALUE;
-
-            url_fseek(bc, -8, SEEK_CUR);
-        }
-    }
-    return AV_NOPTS_VALUE;
-}
-
-static int nut_read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
-//    NUTContext *nut = s->priv_data;
-    int64_t pos;
-
-    if(av_seek_frame_binary(s, stream_index, target_ts, flags) < 0)
-        return -1;
-
-    pos= url_ftell(&s->pb);
-    nut_read_timestamp(s, stream_index, &pos, pos-1);
-
-    return 0;
-}
-
 static int nut_read_close(AVFormatContext *s)
 {
     NUTContext *nut = s->priv_data;
 
+    av_freep(&nut->time_base);
     av_freep(&nut->stream);
 
     return 0;
@@ -1429,29 +684,8 @@
     nut_read_header,
     nut_read_packet,
     nut_read_close,
-    nut_read_seek,
-    nut_read_timestamp,
+    NULL,
+    NULL,
     .extensions = "nut",
 };
 #endif
-#ifdef CONFIG_NUT_MUXER
-AVOutputFormat nut_muxer = {
-    "nut",
-    "nut format",
-    "video/x-nut",
-    "nut",
-    sizeof(NUTContext),
-#ifdef CONFIG_LIBVORBIS
-    CODEC_ID_VORBIS,
-#elif defined(CONFIG_MP3LAME)
-    CODEC_ID_MP3,
-#else
-    CODEC_ID_MP2, /* AC3 needs liba52 decoder */
-#endif
-    CODEC_ID_MPEG4,
-    nut_write_header,
-    nut_write_packet,
-    nut_write_trailer,
-    .flags = AVFMT_GLOBALHEADER,
-};
-#endif




More information about the ffmpeg-cvslog mailing list