]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/nut.c
* providing MPEG codecs with a generic fields in AVFrame to use.
[ffmpeg] / libavformat / nut.c
index 92f478ee244d9935e8782c088e085d758d3ea21b..4a0d9418de201a99164e393cc308dc7b0e507c7a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * NUT (de)muxer based on initial draft
+ * "NUT" Container Format muxer and demuxer (DRAFT-20031003)
  * Copyright (c) 2003 Alex Beregszaszi
  *
  * This library is free software; you can redistribute it and/or
  *
  * NUT DRAFT can be found in MPlayer CVS at DOCS/tech/mpcf.txt
  *
- * Compatible with draft version 20030906
+ * AND http://people.fsn.hu/~alex/nut/ (TeX, pdf, ps, dvi, ..)
  *
  */
 
 /*
  * TODO:
  * - checksumming
- * - correct rate denom/nom and sample_mul
- * - correct timestamp handling
+ * - optimal timestamp handling
  * - index writing
  * - info and index packet reading support
  * - startcode searching for broken streams
  * - subpacket support
- * - handling of codec specific headers
 */
 
 //#define DEBUG 1
@@ -63,7 +61,6 @@ static uint64_t get_v(ByteIOContext *bc)
 {
     uint64_t val = 0;
 
-//    for (; bytes_left(s)*8 > 0; )
     for(; bytes_left(bc) > 0; )
     {
        int tmp = get_byte(bc);
@@ -86,16 +83,29 @@ static int64_t get_s(ByteIOContext *bc)
         return (v>>1);
 }
 
-static int get_b(ByteIOContext *bc)
+static int get_b(ByteIOContext *bc, char *data, int maxlen)
 {
-    int i, len, val;
+    int i, len;
     
     len = get_v(bc);
-    val = 0;
-    for (i = 0; i < len; i++) {
-        if (i < 4)
-            val |= get_byte(bc) << (i * 8);
-    }
+    for (i = 0; i < len && i < maxlen; i++)
+       data[i] = get_byte(bc);
+    /* skip remaining bytes */
+    url_fskip(bc, len-i);
+
+    return 0;
+}
+
+static int get_bi(ByteIOContext *bc)
+{
+   int i, len, val = 0;
+    
+    len = get_v(bc);
+    for (i = 0; i < len && i <= 4; i++)
+        val |= get_byte(bc) << (i * 8);
+    /* skip remaining bytes */
+    url_fskip(bc, len-i);
+
     return val;
 }
 
@@ -123,6 +133,7 @@ static int get_length(uint64_t val){
     return 7; //not reached
 }
 
+#ifdef CONFIG_ENCODERS
 static int put_v(ByteIOContext *bc, uint64_t val)
 {
     int i;
@@ -213,21 +224,12 @@ static int nut_write_header(AVFormatContext *s)
     ByteIOContext *bc = &s->pb;
     AVCodecContext *codec;
     int i;
-    int stream_length = 0;
-
-    for (i = 0; i < s->nb_streams; i++)
-    {
-       if (stream_length < (s->streams[i]->duration * (AV_TIME_BASE / 1000)))
-           stream_length = s->streams[i]->duration * (AV_TIME_BASE / 1000);
-    }
 
     /* main header */
     put_be64(bc, MAIN_STARTCODE);
     put_packetheader(nut, bc, 120);
     put_v(bc, 0); /* version */
     put_v(bc, s->nb_streams);
-    put_v(bc, 0); /* file size */
-    put_v(bc, stream_length); /* len in msec */
     put_be32(bc, 0); /* FIXME: checksum */
     
     update_packetheader(nut, bc, 0);
@@ -235,6 +237,8 @@ static int nut_write_header(AVFormatContext *s)
     /* stream headers */
     for (i = 0; i < s->nb_streams; i++)
     {
+       int nom, denom;
+
        codec = &s->streams[i]->codec;
        
        put_be64(bc, STREAM_STARTCODE);
@@ -253,11 +257,22 @@ static int nut_write_header(AVFormatContext *s)
            int tmp = codec_get_wav_tag(codec->codec_id);
            put_bi(bc, tmp);
        }
+
+       if (codec->codec_type == CODEC_TYPE_VIDEO)
+       {
+           nom = codec->frame_rate;
+           denom = codec->frame_rate_base;
+       }
+       else
+       {
+           nom = codec->sample_rate/8;
+           denom = 8;
+       }
        put_v(bc, codec->bit_rate);
        put_v(bc, 0); /* no language code */
-       put_v(bc, codec->frame_rate_base);
-       put_v(bc, codec->frame_rate);
-       put_v(bc, 0); /* timestamp_shift */
+       put_v(bc, nom);
+       put_v(bc, denom);
+       put_v(bc, 0); /* msb timestamp_shift */
        put_v(bc, 0); /* shuffle type */
        put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
        
@@ -266,7 +281,7 @@ static int nut_write_header(AVFormatContext *s)
        switch(codec->codec_type)
        {
            case CODEC_TYPE_AUDIO:
-               put_v(bc, codec->sample_rate / (double)(codec->frame_rate_base / codec->frame_rate));
+               put_v(bc, (codec->sample_rate * denom) / nom);
                put_v(bc, codec->channels);
                put_be32(bc, 0); /* FIXME: checksum */
                break;
@@ -325,7 +340,7 @@ static int nut_write_header(AVFormatContext *s)
 }
 
 static int nut_write_packet(AVFormatContext *s, int stream_index, 
-                           uint8_t *buf, int size, int force_pts)
+                           const uint8_t *buf, int size, int64_t pts)
 {
     NUTContext *nut = s->priv_data;
     ByteIOContext *bc = &s->pb;
@@ -337,8 +352,7 @@ static int nut_write_packet(AVFormatContext *s, int stream_index,
        return 1;
 
     enc = &s->streams[stream_index]->codec;
-    if (enc->codec_type == CODEC_TYPE_VIDEO)
-       key_frame = enc->coded_frame->key_frame;
+    key_frame = enc->coded_frame->key_frame;
 
     if (key_frame)
        put_be64(bc, KEYFRAME_STARTCODE);
@@ -354,7 +368,7 @@ static int nut_write_packet(AVFormatContext *s, int stream_index,
 
     put_packetheader(nut, bc, size+20);
     put_v(bc, stream_index);
-    put_s(bc, force_pts); /* lsb_timestamp */
+    put_s(bc, pts); /* lsb_timestamp */
     update_packetheader(nut, bc, size);
     
     put_buffer(bc, buf, size);
@@ -387,6 +401,7 @@ static int nut_write_trailer(AVFormatContext *s)
 
     return 0;
 }
+#endif //CONFIG_ENCODERS
 
 static int nut_probe(AVProbeData *p)
 {
@@ -397,7 +412,6 @@ static int nut_probe(AVProbeData *p)
     for (i = 0; i < p->buf_size; i++) {
         int c = p->buf[i];
         code = (code << 8) | c;
-        code &= 0xFFFFFFFFFFFFFFFFULL;
         if (code == MAIN_STARTCODE)
             return AVPROBE_SCORE_MAX;
     }
@@ -422,10 +436,6 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
        fprintf(stderr, "bad version (%Ld)\n", tmp);
     
     nb_streams = get_v(bc);
-    
-    s->file_size = get_v(bc);
-    s->duration = get_v(bc) / (AV_TIME_BASE / 1000);
-
     get_be32(bc); /* checkusm */
     
     s->bit_rate = 0;
@@ -433,7 +443,7 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
     /* stream header */
     for (cur_stream = 0; cur_stream < nb_streams; cur_stream++)
     {
-       int class;
+       int class, nom, denom;
        AVStream *st;
        
        tmp = get_be64(bc);
@@ -444,18 +454,17 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
        if (!st)
            return AVERROR_NOMEM;
        class = get_v(bc);
+       tmp = get_bi(bc);
        switch(class)
        {
            case 0:
                st->codec.codec_type = CODEC_TYPE_VIDEO;
-               tmp = get_b(bc);
                st->codec.codec_id = codec_get_bmp_id(tmp);
                if (st->codec.codec_id == CODEC_ID_NONE)
                    fprintf(stderr, "Unknown codec?!\n");
                break;
            case 32:
                st->codec.codec_type = CODEC_TYPE_AUDIO;
-               tmp = get_b(bc);
                st->codec.codec_id = codec_get_wav_id(tmp);
                if (st->codec.codec_id == CODEC_ID_NONE)
                    fprintf(stderr, "Unknown codec?!\n");
@@ -465,16 +474,16 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
                return -1;
        }
        s->bit_rate += get_v(bc);
-       tmp = get_v(bc); /* language code */
-       while(tmp--)
-           get_byte(bc);
-       st->codec.frame_rate_base = get_v(bc);
-       st->codec.frame_rate = get_v(bc);
+       get_b(bc, NULL, 0); /* language code */
+       nom = get_v(bc);
+       denom = get_v(bc);
        get_v(bc); /* FIXME: msb timestamp base */
        get_v(bc); /* shuffle type */
        get_byte(bc); /* flags */
-       
-       get_v(bc); /* FIXME: codec specific data headers */
+
+       /* codec specific data headers */
+       while(get_v(bc) != 0)
+           url_fskip(bc, get_v(bc));
        
        if (class == 0) /* VIDEO */
        {
@@ -483,13 +492,16 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
            get_v(bc); /* aspected w */
            get_v(bc); /* aspected h */
            get_v(bc); /* csp type */
-           get_le32(bc); /* checksum */
+           get_be32(bc); /* checksum */
+
+           st->codec.frame_rate = nom;
+           st->codec.frame_rate_base = denom;
        }
        if (class == 32) /* AUDIO */
        {
-           st->codec.sample_rate = get_v(bc) * (double)(st->codec.frame_rate_base / st->codec.frame_rate);
+           st->codec.sample_rate = (get_v(bc) * nom) / denom;
            st->codec.channels = get_v(bc);
-           get_le32(bc); /* checksum */
+           get_be32(bc); /* checksum */
        }
     }    
     
@@ -558,6 +570,7 @@ static AVInputFormat nut_iformat = {
     .extensions = "nut",
 };
 
+#ifdef CONFIG_ENCODERS
 static AVOutputFormat nut_oformat = {
     "nut",
     "nut format",
@@ -567,7 +580,7 @@ static AVOutputFormat nut_oformat = {
 #ifdef CONFIG_VORBIS
     CODEC_ID_VORBIS,
 #elif defined(CONFIG_MP3LAME)
-    CODEC_ID_MP3LAME,
+    CODEC_ID_MP3,
 #else
     CODEC_ID_MP2, /* AC3 needs liba52 decoder */
 #endif
@@ -576,10 +589,13 @@ static AVOutputFormat nut_oformat = {
     nut_write_packet,
     nut_write_trailer,
 };
+#endif //CONFIG_ENCODERS
 
 int nut_init(void)
 {
     av_register_input_format(&nut_iformat);
+#ifdef CONFIG_ENCODERS
     av_register_output_format(&nut_oformat);
+#endif //CONFIG_ENCODERS
     return 0;
 }