Statistics
| Branch: | Revision:

ffmpeg / libavformat / nut.c @ 4b684105

History | View | Annotate | Download (13.6 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
#ifdef CONFIG_ENCODERS
137
static int put_v(ByteIOContext *bc, uint64_t val)
138
{
139
    int i;
140

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

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

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

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

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

    
156
    return 0;
157
}
158

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

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

    
175
    return 0;
176
}
177

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

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

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

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

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

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

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

    
242
        codec = &s->streams[i]->codec;
243
        
244
        put_be64(bc, STREAM_STARTCODE);
245
        put_packetheader(nut, bc, 120);
246
        put_v(bc, i /*s->streams[i]->index*/);
247
        put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0);
248
        if (codec->codec_tag)
249
            put_bi(bc, codec->codec_tag);
250
        else if (codec->codec_type == CODEC_TYPE_VIDEO)
251
        {
252
            int tmp = codec_get_bmp_tag(codec->codec_id);
253
            put_bi(bc, tmp);
254
        }
255
        else if (codec->codec_type == CODEC_TYPE_AUDIO)
256
        {
257
            int tmp = codec_get_wav_tag(codec->codec_id);
258
            put_bi(bc, tmp);
259
        }
260

    
261
        if (codec->codec_type == CODEC_TYPE_VIDEO)
262
        {
263
            nom = codec->frame_rate;
264
            denom = codec->frame_rate_base;
265
        }
266
        else
267
        {
268
            nom = codec->sample_rate/8;
269
            denom = 8;
270
        }
271
        put_v(bc, codec->bit_rate);
272
        put_v(bc, 0); /* no language code */
273
        put_v(bc, nom);
274
        put_v(bc, denom);
275
        put_v(bc, 0); /* msb timestamp_shift */
276
        put_v(bc, 0); /* shuffle type */
277
        put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
278
        
279
        put_v(bc, 0); /* no codec specific headers */
280
        
281
        switch(codec->codec_type)
282
        {
283
            case CODEC_TYPE_AUDIO:
284
                put_v(bc, (codec->sample_rate * denom) / nom);
285
                put_v(bc, codec->channels);
286
                put_be32(bc, 0); /* FIXME: checksum */
287
                break;
288
            case CODEC_TYPE_VIDEO:
289
                put_v(bc, codec->width);
290
                put_v(bc, codec->height);
291
                put_v(bc, 0); /* aspected w */
292
                put_v(bc, 0); /* aspected h */
293
                put_v(bc, 0); /* csp type -- unknown */
294
                put_be32(bc, 0); /* FIXME: checksum */
295
                break;
296
            default:
297
                break;
298
        }
299
        update_packetheader(nut, bc, 0);
300
    }
301

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

333
    put_be32(bc, 0); /* FIXME: checksum */
334
    update_packetheader(nut, bc, 0);
335
#endif
336
        
337
    put_flush_packet(bc);
338
    
339
    return 0;
340
}
341

    
342
static int nut_write_packet(AVFormatContext *s, int stream_index, 
343
                            const uint8_t *buf, int size, int64_t pts)
344
{
345
    NUTContext *nut = s->priv_data;
346
    ByteIOContext *bc = &s->pb;
347
    int key_frame = 0;
348
    int flags;
349
    AVCodecContext *enc;
350

    
351
    if (stream_index > s->nb_streams)
352
        return 1;
353

    
354
    enc = &s->streams[stream_index]->codec;
355
    key_frame = enc->coded_frame->key_frame;
356

    
357
    if (key_frame)
358
        put_be64(bc, KEYFRAME_STARTCODE);
359
    
360
    flags=0;
361
    flags<<=2; flags|=1; //priority
362
    flags<<=1; flags|=0; //checksum
363
    flags<<=1; flags|=0; //msb_timestamp_flag
364
    flags<<=2; flags|=1; //subpacket_type
365
    flags<<=1; flags|=0; //reserved
366

    
367
    put_byte(bc, flags);
368

    
369
    put_packetheader(nut, bc, size+20);
370
    put_v(bc, stream_index);
371
    put_s(bc, pts); /* lsb_timestamp */
372
    update_packetheader(nut, bc, size);
373
    
374
    put_buffer(bc, buf, size);
375
    
376
    put_flush_packet(bc);
377

    
378
    return 0;
379
}
380

    
381
static int nut_write_trailer(AVFormatContext *s)
382
{
383
    ByteIOContext *bc = &s->pb;
384
#if 0
385
    int i;
386

387
    /* WRITE INDEX */
388

389
    for (i = 0; s->nb_streams; i++)
390
    {
391
        put_be64(bc, INDEX_STARTCODE);
392
        put_packetheader(nut, bc, 64);
393
        put_v(bc, s->streams[i]->id);
394
        put_v(bc, ...);
395
        put_be32(bc, 0); /* FIXME: checksum */
396
        update_packetheader(nut, bc, 0);
397
    }
398
#endif
399

    
400
    put_flush_packet(bc);
401

    
402
    return 0;
403
}
404
#endif //CONFIG_ENCODERS
405

    
406
static int nut_probe(AVProbeData *p)
407
{
408
    int i;
409
    uint64_t code;
410

    
411
    code = 0xff;
412
    for (i = 0; i < p->buf_size; i++) {
413
        int c = p->buf[i];
414
        code = (code << 8) | c;
415
        if (code == MAIN_STARTCODE)
416
            return AVPROBE_SCORE_MAX;
417
    }
418
    return 0;
419
}
420

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

    
484
        /* codec specific data headers */
485
        while(get_v(bc) != 0)
486
            url_fskip(bc, get_v(bc));
487
        
488
        if (class == 0) /* VIDEO */
489
        {
490
            st->codec.width = get_v(bc);
491
            st->codec.height = get_v(bc);
492
            get_v(bc); /* aspected w */
493
            get_v(bc); /* aspected h */
494
            get_v(bc); /* csp type */
495
            get_be32(bc); /* checksum */
496

    
497
            st->codec.frame_rate = nom;
498
            st->codec.frame_rate_base = denom;
499
        }
500
        if (class == 32) /* AUDIO */
501
        {
502
            st->codec.sample_rate = (get_v(bc) * nom) / denom;
503
            st->codec.channels = get_v(bc);
504
            get_be32(bc); /* checksum */
505
        }
506
    }    
507
    
508
    return 0;
509
}
510

    
511
static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
512
{
513
    NUTContext *nut = s->priv_data;
514
    ByteIOContext *bc = &s->pb;
515
    int id, timestamp, size;
516
    int key_frame = 0;
517
    uint64_t tmp;
518

    
519

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

    
551
    av_new_packet(pkt, size);
552
    get_buffer(bc, pkt->data, size);
553
    pkt->stream_index = id;
554
    if (key_frame)
555
        pkt->flags |= PKT_FLAG_KEY;
556
    pkt->pts = timestamp;
557

    
558
    return 0;
559
}
560

    
561
static AVInputFormat nut_iformat = {
562
    "nut",
563
    "nut format",
564
    sizeof(NUTContext),
565
    nut_probe,
566
    nut_read_header,
567
    nut_read_packet,
568
//    nut_read_close,
569
//    nut_read_seek,
570
    .extensions = "nut",
571
};
572

    
573
#ifdef CONFIG_ENCODERS
574
static AVOutputFormat nut_oformat = {
575
    "nut",
576
    "nut format",
577
    "video/x-nut",
578
    "nut",
579
    sizeof(NUTContext),
580
#ifdef CONFIG_VORBIS
581
    CODEC_ID_VORBIS,
582
#elif defined(CONFIG_MP3LAME)
583
    CODEC_ID_MP3,
584
#else
585
    CODEC_ID_MP2, /* AC3 needs liba52 decoder */
586
#endif
587
    CODEC_ID_MPEG4,
588
    nut_write_header,
589
    nut_write_packet,
590
    nut_write_trailer,
591
};
592
#endif //CONFIG_ENCODERS
593

    
594
int nut_init(void)
595
{
596
    av_register_input_format(&nut_iformat);
597
#ifdef CONFIG_ENCODERS
598
    av_register_output_format(&nut_oformat);
599
#endif //CONFIG_ENCODERS
600
    return 0;
601
}