Statistics
| Branch: | Revision:

ffmpeg / libavformat / nut.c @ 20f269dc

History | View | Annotate | Download (13.4 KB)

1
/*
2
 * "NUT" Container Format muxer and demuxer (DRAFT-20031003)
3
 * Copyright (c) 2003 Alex Beregszaszi
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 *
19
 * NUT DRAFT can be found in MPlayer CVS at DOCS/tech/mpcf.txt
20
 *
21
 * AND http://people.fsn.hu/~alex/nut/ (TeX, pdf, ps, dvi, ..)
22
 *
23
 */
24

    
25
/*
26
 * TODO:
27
 * - checksumming
28
 * - optimal timestamp handling
29
 * - index writing
30
 * - info and index packet reading support
31
 * - startcode searching for broken streams
32
 * - subpacket support
33
*/
34

    
35
//#define DEBUG 1
36

    
37
#include "avformat.h"
38
#include "mpegaudio.h"
39
#include "avi.h"
40

    
41
//from /dev/random
42

    
43
#define     MAIN_STARTCODE (0xF9526A6200000000ULL + ('N'<<24) + ('U'<<16) + ('T'<<8) + 'M')
44
#define   STREAM_STARTCODE (0xD667773F00000000ULL + ('N'<<24) + ('U'<<16) + ('T'<<8) + 'S')
45
#define KEYFRAME_STARTCODE (0xCB86308700000000ULL + ('N'<<24) + ('U'<<16) + ('T'<<8) + 'K')
46
#define    INDEX_STARTCODE (0xEBFCDE0E00000000ULL + ('N'<<24) + ('U'<<16) + ('T'<<8) + 'X')
47
#define     INFO_STARTCODE (0xA37B643500000000ULL + ('N'<<24) + ('U'<<16) + ('T'<<8) + 'I')
48

    
49
typedef struct {
50
    int curr_frame_start;
51
    int last_frame_size;
52
    int curr_frame_size;
53
} NUTContext;
54

    
55
static int bytes_left(ByteIOContext *bc)
56
{
57
    return bc->buf_end - bc->buf_ptr;
58
}
59

    
60
static uint64_t get_v(ByteIOContext *bc)
61
{
62
    uint64_t val = 0;
63

    
64
    for(; bytes_left(bc) > 0; )
65
    {
66
        int tmp = get_byte(bc);
67

    
68
        if (tmp&0x80)
69
            val= (val<<7) + tmp - 0x80;
70
        else
71
            return (val<<7) + tmp;
72
    }
73
    return -1;
74
}
75

    
76
static int64_t get_s(ByteIOContext *bc)
77
{
78
    int64_t v = get_v(bc) + 1;
79

    
80
    if (v&1)
81
        return -(v>>1);
82
    else
83
        return (v>>1);
84
}
85

    
86
static int get_b(ByteIOContext *bc, char *data, int maxlen)
87
{
88
    int i, len;
89
    
90
    len = get_v(bc);
91
    for (i = 0; i < len && i < maxlen; i++)
92
        data[i] = get_byte(bc);
93
    /* skip remaining bytes */
94
    url_fskip(bc, len-i);
95

    
96
    return 0;
97
}
98

    
99
static int get_bi(ByteIOContext *bc)
100
{
101
   int i, len, val = 0;
102
    
103
    len = get_v(bc);
104
    for (i = 0; i < len && i <= 4; i++)
105
        val |= get_byte(bc) << (i * 8);
106
    /* skip remaining bytes */
107
    url_fskip(bc, len-i);
108

    
109
    return val;
110
}
111

    
112
static int get_packetheader(NUTContext *nut, ByteIOContext *bc)
113
{
114
    nut->curr_frame_start = url_ftell(bc);
115
    nut->curr_frame_size = get_v(bc);
116
    nut->last_frame_size = get_v(bc);
117
    dprintf("Packet: fwd: %d bwd: %d\n",
118
        nut->curr_frame_size, nut->last_frame_size);
119
    
120
    return 0;
121
}
122

    
123
/**
124
 * 
125
 */
126
static int get_length(uint64_t val){
127
    int i;
128

    
129
    for (i=7; ; i+=7)
130
        if ((val>>i) == 0)
131
            return i;
132

    
133
    return 7; //not reached
134
}
135

    
136
static int put_v(ByteIOContext *bc, uint64_t val)
137
{
138
    int i;
139

    
140
//    if (bytes_left(s)*8 < 9)
141
//        return -1;
142

    
143
    if (bytes_left(bc) < 1)
144
        return -1;
145

    
146
    val &= 0x7FFFFFFFFFFFFFFFULL; // FIXME can only encode upto 63 bits currently
147
    i= get_length(val);
148

    
149
    for (i-=7; i>0; i-=7){
150
        put_byte(bc, 0x80 | (val>>i));
151
    }
152

    
153
    put_byte(bc, val&0x7f);
154

    
155
    return 0;
156
}
157

    
158
static int put_s(ByteIOContext *bc, uint64_t val)
159
{
160
    if (val<=0)
161
        return put_v(bc, -2*val);
162
    else
163
        return put_v(bc, 2*val-1);
164
}
165

    
166
static int put_b(ByteIOContext *bc, char *data, int len)
167
{
168
    int i;
169
    
170
    put_v(bc, len);
171
    for (i = 0; i < len; i++)
172
        put_byte(bc, data[i]);
173

    
174
    return 0;
175
}
176

    
177
static int put_bi(ByteIOContext *bc, int val)
178
{
179
    put_v(bc, 4);
180
    put_le32(bc, val);
181
    return 0;
182
}
183

    
184
static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size)
185
{
186
    put_flush_packet(bc);
187
    nut->curr_frame_start = url_ftell(bc);
188
    nut->curr_frame_size = max_size;
189
    
190
    /* packet header */
191
    put_v(bc, nut->curr_frame_size); /* forward ptr */
192
    put_v(bc, nut->last_frame_size); /* backward ptr */
193
    dprintf("Packet: fwd: %d, bwd: %d\n",
194
        nut->curr_frame_size, nut->last_frame_size);
195

    
196
    nut->last_frame_size = nut->curr_frame_size;
197
    
198
    return 0;
199
}
200

    
201
static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size){
202
    offset_t start= nut->curr_frame_start;
203
    offset_t cur= url_ftell(bc);
204
    int size= cur - start + additional_size;
205
    
206
    assert( size <= nut->curr_frame_size );
207
    
208
    url_fseek(bc, start, SEEK_SET);
209
    put_v(bc, size);
210
    if(get_length(size) < get_length(nut->curr_frame_size))
211
        put_byte(bc, 0x80);
212
    nut->curr_frame_size= size;
213
    dprintf("Packet update: size: %d\n", size);
214

    
215
    url_fseek(bc, cur, SEEK_SET);    
216
    
217
    return 0;
218
}
219

    
220
static int nut_write_header(AVFormatContext *s)
221
{
222
    NUTContext *nut = s->priv_data;
223
    ByteIOContext *bc = &s->pb;
224
    AVCodecContext *codec;
225
    int i;
226

    
227
    /* main header */
228
    put_be64(bc, MAIN_STARTCODE);
229
    put_packetheader(nut, bc, 120);
230
    put_v(bc, 0); /* version */
231
    put_v(bc, s->nb_streams);
232
    put_be32(bc, 0); /* FIXME: checksum */
233
    
234
    update_packetheader(nut, bc, 0);
235
    
236
    /* stream headers */
237
    for (i = 0; i < s->nb_streams; i++)
238
    {
239
        int nom, denom;
240

    
241
        codec = &s->streams[i]->codec;
242
        
243
        put_be64(bc, STREAM_STARTCODE);
244
        put_packetheader(nut, bc, 120);
245
        put_v(bc, i /*s->streams[i]->index*/);
246
        put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0);
247
        if (codec->codec_tag)
248
            put_bi(bc, codec->codec_tag);
249
        else if (codec->codec_type == CODEC_TYPE_VIDEO)
250
        {
251
            int tmp = codec_get_bmp_tag(codec->codec_id);
252
            put_bi(bc, tmp);
253
            nom = codec->frame_rate;
254
            denom = codec->frame_rate_base;
255
        }
256
        else if (codec->codec_type == CODEC_TYPE_AUDIO)
257
        {
258
            int tmp = codec_get_wav_tag(codec->codec_id);
259
            put_bi(bc, tmp);
260
            nom = codec->sample_rate/8;
261
            denom = 8;
262
        }
263
        put_v(bc, codec->bit_rate);
264
        put_v(bc, 0); /* no language code */
265
        put_v(bc, nom);
266
        put_v(bc, denom);
267
        put_v(bc, 0); /* msb timestamp_shift */
268
        put_v(bc, 0); /* shuffle type */
269
        put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
270
        
271
        put_v(bc, 0); /* no codec specific headers */
272
        
273
        switch(codec->codec_type)
274
        {
275
            case CODEC_TYPE_AUDIO:
276
                put_v(bc, (codec->sample_rate * denom) / nom);
277
                put_v(bc, codec->channels);
278
                put_be32(bc, 0); /* FIXME: checksum */
279
                break;
280
            case CODEC_TYPE_VIDEO:
281
                put_v(bc, codec->width);
282
                put_v(bc, codec->height);
283
                put_v(bc, 0); /* aspected w */
284
                put_v(bc, 0); /* aspected h */
285
                put_v(bc, 0); /* csp type -- unknown */
286
                put_be32(bc, 0); /* FIXME: checksum */
287
                break;
288
            default:
289
                break;
290
        }
291
        update_packetheader(nut, bc, 0);
292
    }
293

    
294
#if 0
295
    /* info header */
296
    put_be64(bc, INFO_STARTCODE);
297
    put_packetheader(nut, bc, 16+strlen(s->author)+strlen(s->title)+
298
        strlen(s->comment)+strlen(s->copyright)); 
299
    if (s->author[0])
300
    {
301
        put_v(bc, 5); /* type */
302
        put_b(bc, s->author, strlen(s->author));
303
    }
304
    if (s->title[0])
305
    {
306
        put_v(bc, 6); /* type */
307
        put_b(bc, s->title, strlen(s->title));
308
    }
309
    if (s->comment[0])
310
    {
311
        put_v(bc, 7); /* type */
312
        put_b(bc, s->comment, strlen(s->comment));
313
    }
314
    if (s->copyright[0])
315
    {
316
        put_v(bc, 8); /* type */
317
        put_b(bc, s->copyright, strlen(s->copyright));
318
    }
319
    /* encoder */
320
    put_v(bc, 9); /* type */
321
    put_b(bc, LIBAVFORMAT_IDENT "\0", strlen(LIBAVFORMAT_IDENT));
322
    
323
    put_v(bc, 0); /* eof info */
324

325
    put_be32(bc, 0); /* FIXME: checksum */
326
    update_packetheader(nut, bc, 0);
327
#endif
328
        
329
    put_flush_packet(bc);
330
    
331
    return 0;
332
}
333

    
334
static int nut_write_packet(AVFormatContext *s, int stream_index, 
335
                            const uint8_t *buf, int size, int64_t pts)
336
{
337
    NUTContext *nut = s->priv_data;
338
    ByteIOContext *bc = &s->pb;
339
    int key_frame = 0;
340
    int flags;
341
    AVCodecContext *enc;
342

    
343
    if (stream_index > s->nb_streams)
344
        return 1;
345

    
346
    enc = &s->streams[stream_index]->codec;
347
    key_frame = enc->coded_frame->key_frame;
348

    
349
    if (key_frame)
350
        put_be64(bc, KEYFRAME_STARTCODE);
351
    
352
    flags=0;
353
    flags<<=2; flags|=1; //priority
354
    flags<<=1; flags|=0; //checksum
355
    flags<<=1; flags|=0; //msb_timestamp_flag
356
    flags<<=2; flags|=1; //subpacket_type
357
    flags<<=1; flags|=0; //reserved
358

    
359
    put_byte(bc, flags);
360

    
361
    put_packetheader(nut, bc, size+20);
362
    put_v(bc, stream_index);
363
    put_s(bc, pts); /* lsb_timestamp */
364
    update_packetheader(nut, bc, size);
365
    
366
    put_buffer(bc, buf, size);
367
    
368
    put_flush_packet(bc);
369

    
370
    return 0;
371
}
372

    
373
static int nut_write_trailer(AVFormatContext *s)
374
{
375
    ByteIOContext *bc = &s->pb;
376
#if 0
377
    int i;
378

379
    /* WRITE INDEX */
380

381
    for (i = 0; s->nb_streams; i++)
382
    {
383
        put_be64(bc, INDEX_STARTCODE);
384
        put_packetheader(nut, bc, 64);
385
        put_v(bc, s->streams[i]->id);
386
        put_v(bc, ...);
387
        put_be32(bc, 0); /* FIXME: checksum */
388
        update_packetheader(nut, bc, 0);
389
    }
390
#endif
391

    
392
    put_flush_packet(bc);
393

    
394
    return 0;
395
}
396

    
397
static int nut_probe(AVProbeData *p)
398
{
399
    int i;
400
    uint64_t code;
401

    
402
    code = 0xff;
403
    for (i = 0; i < p->buf_size; i++) {
404
        int c = p->buf[i];
405
        code = (code << 8) | c;
406
        if (code == MAIN_STARTCODE)
407
            return AVPROBE_SCORE_MAX;
408
    }
409
    return 0;
410
}
411

    
412
static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
413
{
414
    NUTContext *nut = s->priv_data;
415
    ByteIOContext *bc = &s->pb;
416
    uint64_t tmp;
417
    int cur_stream, nb_streams;
418
    
419
    /* main header */
420
    tmp = get_be64(bc);
421
    if (tmp != MAIN_STARTCODE)
422
        fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
423
    get_packetheader(nut, bc);
424
    
425
    tmp = get_v(bc);
426
    if (tmp != 0)
427
        fprintf(stderr, "bad version (%Ld)\n", tmp);
428
    
429
    nb_streams = get_v(bc);
430
    get_be32(bc); /* checkusm */
431
    
432
    s->bit_rate = 0;
433
    
434
    /* stream header */
435
    for (cur_stream = 0; cur_stream < nb_streams; cur_stream++)
436
    {
437
        int class, nom, denom;
438
        AVStream *st;
439
        
440
        tmp = get_be64(bc);
441
        if (tmp != STREAM_STARTCODE)
442
            fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
443
        get_packetheader(nut, bc);
444
        st = av_new_stream(s, get_v(bc));
445
        if (!st)
446
            return AVERROR_NOMEM;
447
        class = get_v(bc);
448
        tmp = get_bi(bc);
449
        switch(class)
450
        {
451
            case 0:
452
                st->codec.codec_type = CODEC_TYPE_VIDEO;
453
                st->codec.codec_id = codec_get_bmp_id(tmp);
454
                if (st->codec.codec_id == CODEC_ID_NONE)
455
                    fprintf(stderr, "Unknown codec?!\n");
456
                break;
457
            case 32:
458
                st->codec.codec_type = CODEC_TYPE_AUDIO;
459
                st->codec.codec_id = codec_get_wav_id(tmp);
460
                if (st->codec.codec_id == CODEC_ID_NONE)
461
                    fprintf(stderr, "Unknown codec?!\n");
462
                break;
463
            default:
464
                fprintf(stderr, "Unknown stream class (%d)\n", class);
465
                return -1;
466
        }
467
        s->bit_rate += get_v(bc);
468
        get_b(bc, NULL, 0); /* language code */
469
        nom = get_v(bc);
470
        denom = get_v(bc);
471
        get_v(bc); /* FIXME: msb timestamp base */
472
        get_v(bc); /* shuffle type */
473
        get_byte(bc); /* flags */
474

    
475
        /* codec specific data headers */
476
        while(get_v(bc) != 0)
477
            url_fskip(bc, get_v(bc));
478
        
479
        if (class == 0) /* VIDEO */
480
        {
481
            st->codec.width = get_v(bc);
482
            st->codec.height = get_v(bc);
483
            get_v(bc); /* aspected w */
484
            get_v(bc); /* aspected h */
485
            get_v(bc); /* csp type */
486
            get_be32(bc); /* checksum */
487

    
488
            st->codec.frame_rate = nom;
489
            st->codec.frame_rate_base = denom;
490
        }
491
        if (class == 32) /* AUDIO */
492
        {
493
            st->codec.sample_rate = (get_v(bc) * nom) / denom;
494
            st->codec.channels = get_v(bc);
495
            get_be32(bc); /* checksum */
496
        }
497
    }    
498
    
499
    return 0;
500
}
501

    
502
static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
503
{
504
    NUTContext *nut = s->priv_data;
505
    ByteIOContext *bc = &s->pb;
506
    int id, timestamp, size;
507
    int key_frame = 0;
508
    uint64_t tmp;
509

    
510

    
511
    if (url_feof(bc))
512
        return -1;
513
    
514
    tmp = get_byte(bc);
515
    if (tmp & 0x80) /* zero bit set? */
516
    {
517
        tmp<<=8 ; tmp |= get_byte(bc);
518
        tmp<<=16; tmp |= get_be16(bc);
519
        tmp<<=32; tmp |= get_be32(bc);
520
        if (tmp == KEYFRAME_STARTCODE)
521
        {
522
            key_frame = 1;
523
            tmp = get_byte(bc); /* flags */
524
        }
525
        else
526
            fprintf(stderr, "error in zero bit / startcode %LX\n", tmp);
527
    }
528
    get_packetheader(nut, bc);
529
#if 0
530
    if (((tmp & 0x60)>>5) > 3) /* priority <= 3 */
531
        fprintf(stderr, "sanity check failed!\n");
532
#endif
533
    id = get_v(bc);
534
    timestamp = get_s(bc);
535
    
536
    size = (nut->curr_frame_size - (url_ftell(bc)-nut->curr_frame_start));
537
    dprintf("flags: 0x%Lx, timestamp: %d, packet size: %d\n", tmp, timestamp, size);
538
    
539
    if (size < 0)
540
        return -1;
541

    
542
    av_new_packet(pkt, size);
543
    get_buffer(bc, pkt->data, size);
544
    pkt->stream_index = id;
545
    if (key_frame)
546
        pkt->flags |= PKT_FLAG_KEY;
547
    pkt->pts = timestamp;
548

    
549
    return 0;
550
}
551

    
552
static AVInputFormat nut_iformat = {
553
    "nut",
554
    "nut format",
555
    sizeof(NUTContext),
556
    nut_probe,
557
    nut_read_header,
558
    nut_read_packet,
559
//    nut_read_close,
560
//    nut_read_seek,
561
    .extensions = "nut",
562
};
563

    
564
static AVOutputFormat nut_oformat = {
565
    "nut",
566
    "nut format",
567
    "video/x-nut",
568
    "nut",
569
    sizeof(NUTContext),
570
#ifdef CONFIG_VORBIS
571
    CODEC_ID_VORBIS,
572
#elif defined(CONFIG_MP3LAME)
573
    CODEC_ID_MP3,
574
#else
575
    CODEC_ID_MP2, /* AC3 needs liba52 decoder */
576
#endif
577
    CODEC_ID_MPEG4,
578
    nut_write_header,
579
    nut_write_packet,
580
    nut_write_trailer,
581
};
582

    
583
int nut_init(void)
584
{
585
    av_register_input_format(&nut_iformat);
586
    av_register_output_format(&nut_oformat);
587
    return 0;
588
}