Statistics
| Branch: | Revision:

ffmpeg / libavformat / nut.c @ 203504d9

History | View | Annotate | Download (13.7 KB)

1 3aa180b8 Alex Beregszaszi
/*
2
 * NUT (de)muxer based on initial draft
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
 * Compatible with draft version 20030906
22
 *
23
 */
24
25
/*
26
 * TODO:
27
 * - checksumming
28
 * - correct rate denom/nom and sample_mul
29
 * - correct timestamp handling
30
 * - index writing
31
 * - info and index packet reading support
32
 * - startcode searching for broken streams
33
 * - subpacket support
34
 * - handling of codec specific headers
35
*/
36
37
//#define DEBUG 1
38
39
#include "avformat.h"
40
#include "mpegaudio.h"
41
42 3ac8749b Michael Niedermayer
//from /dev/random
43
44
#define     MAIN_STARTCODE (0xF9526A6200000000ULL + ('N'<<24) + ('U'<<16) + ('T'<<8) + 'M')
45
#define   STREAM_STARTCODE (0xD667773F00000000ULL + ('N'<<24) + ('U'<<16) + ('T'<<8) + 'S')
46
#define KEYFRAME_STARTCODE (0xCB86308700000000ULL + ('N'<<24) + ('U'<<16) + ('T'<<8) + 'K')
47
#define    INDEX_STARTCODE (0xEBFCDE0E00000000ULL + ('N'<<24) + ('U'<<16) + ('T'<<8) + 'X')
48
#define     INFO_STARTCODE (0xA37B643500000000ULL + ('N'<<24) + ('U'<<16) + ('T'<<8) + 'I')
49
50 3aa180b8 Alex Beregszaszi
typedef struct {
51
    int curr_frame_start;
52
    int last_frame_size;
53
    int curr_frame_size;
54
} NUTContext;
55
56
static int bytes_left(ByteIOContext *bc)
57
{
58
    return bc->buf_end - bc->buf_ptr;
59
}
60
61
static uint64_t get_v(ByteIOContext *bc)
62
{
63
    uint64_t val = 0;
64
65
//    for (; bytes_left(s)*8 > 0; )
66
    for(; bytes_left(bc) > 0; )
67
    {
68
        int tmp = get_byte(bc);
69
70
        if (tmp&0x80)
71
            val= (val<<7) + tmp - 0x80;
72
        else
73
            return (val<<7) + tmp;
74
    }
75
    return -1;
76
}
77
78
static int64_t get_s(ByteIOContext *bc)
79
{
80
    int64_t v = get_v(bc) + 1;
81
82
    if (v&1)
83
        return -(v>>1);
84
    else
85
        return (v>>1);
86
}
87
88
static int get_b(ByteIOContext *bc, char *data, int maxlen)
89
{
90
    int i, len;
91
    
92
    len = get_v(bc);
93
    for (i = 0; i < len && i < maxlen; i++)
94
        data[i] = get_byte(bc);
95
    if (i < len)
96
    {
97
        len = i;
98
        for (i = 0; i < len; i++)
99
            get_byte(bc);
100
    }
101
102
    return 0;
103
}
104
105
static int get_packetheader(NUTContext *nut, ByteIOContext *bc)
106
{
107
    nut->curr_frame_start = url_ftell(bc);
108
    nut->curr_frame_size = get_v(bc);
109
    nut->last_frame_size = get_v(bc);
110
    dprintf("Packet: fwd: %d bwd: %d\n",
111
        nut->curr_frame_size, nut->last_frame_size);
112
    
113
    return 0;
114
}
115
116 203504d9 Michael Niedermayer
/**
117
 * 
118
 */
119
static int get_length(uint64_t val){
120
    int i;
121 3aa180b8 Alex Beregszaszi
122 203504d9 Michael Niedermayer
    for (i=7; ; i+=7)
123
        if ((val>>i) == 0)
124
            return i;
125 3aa180b8 Alex Beregszaszi
126 203504d9 Michael Niedermayer
    return 7; //not reached
127 3aa180b8 Alex Beregszaszi
}
128
129
static int put_v(ByteIOContext *bc, uint64_t val)
130
{
131
    int i;
132
133
//    if (bytes_left(s)*8 < 9)
134
//        return -1;
135
136
    if (bytes_left(bc) < 1)
137
        return -1;
138
139
    val &= 0x7FFFFFFFFFFFFFFFULL; // FIXME can only encode upto 63 bits currently
140 203504d9 Michael Niedermayer
    i= get_length(val);
141 3aa180b8 Alex Beregszaszi
142 3ac8749b Michael Niedermayer
    for (i-=7; i>0; i-=7){
143 3aa180b8 Alex Beregszaszi
        put_byte(bc, 0x80 | (val>>i));
144 3ac8749b Michael Niedermayer
    }
145 3aa180b8 Alex Beregszaszi
146
    put_byte(bc, val&0x7f);
147
148
    return 0;
149
}
150
151
static int put_s(ByteIOContext *bc, uint64_t val)
152
{
153
    if (val<=0)
154
        return put_v(bc, -2*val);
155
    else
156
        return put_v(bc, 2*val-1);
157
}
158
159
static int put_b(ByteIOContext *bc, char *data, int len)
160
{
161
    int i;
162
    
163
    put_v(bc, len);
164
    for (i = 0; i < len; i++)
165
        put_byte(bc, data[i]);
166
167
    return 0;
168
}
169
170 203504d9 Michael Niedermayer
static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size)
171 3aa180b8 Alex Beregszaszi
{
172
    put_flush_packet(bc);
173
    nut->curr_frame_start = url_ftell(bc);
174 203504d9 Michael Niedermayer
    nut->curr_frame_size = max_size;
175 3aa180b8 Alex Beregszaszi
    
176
    /* packet header */
177
    put_v(bc, nut->curr_frame_size); /* forward ptr */
178
    put_v(bc, nut->last_frame_size); /* backward ptr */
179
    dprintf("Packet: fwd: %d, bwd: %d\n",
180
        nut->curr_frame_size, nut->last_frame_size);
181
182
    nut->last_frame_size = nut->curr_frame_size;
183
    
184
    return 0;
185
}
186
187 203504d9 Michael Niedermayer
static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size){
188
    offset_t start= nut->curr_frame_start;
189
    offset_t cur= url_ftell(bc);
190
    int size= cur - start + additional_size;
191
    
192
    assert( size <= nut->curr_frame_size );
193
    
194
    url_fseek(bc, start, SEEK_SET);
195
    put_v(bc, size);
196
    if(get_length(size) < get_length(nut->curr_frame_size))
197
        put_byte(bc, 0x80);
198
    nut->curr_frame_size= size;
199
    dprintf("Packet update: size: %d\n", size);
200
201
    url_fseek(bc, cur, SEEK_SET);    
202 3aa180b8 Alex Beregszaszi
    
203
    return 0;
204
}
205
206
static int nut_write_header(AVFormatContext *s)
207
{
208
    NUTContext *nut = s->priv_data;
209
    ByteIOContext *bc = &s->pb;
210
    AVCodecContext *codec;
211
    int i;
212
    int stream_length = 0;
213
214
    for (i = 0; i < s->nb_streams; i++)
215
    {
216
        if (stream_length < (s->streams[i]->duration * (AV_TIME_BASE / 1000)))
217
            stream_length = s->streams[i]->duration * (AV_TIME_BASE / 1000);
218
    }
219
220 203504d9 Michael Niedermayer
    put_packetheader(nut, bc, 120);
221 3aa180b8 Alex Beregszaszi
    
222
    /* main header */
223 3ac8749b Michael Niedermayer
    put_be64(bc, MAIN_STARTCODE);
224 3aa180b8 Alex Beregszaszi
    put_v(bc, 0); /* version */
225
    put_v(bc, s->nb_streams);
226
    put_v(bc, 0); /* file size */
227
    put_v(bc, stream_length); /* len in msec */
228 3ac8749b Michael Niedermayer
    put_be32(bc, 0); /* FIXME: checksum */
229 3aa180b8 Alex Beregszaszi
    
230 203504d9 Michael Niedermayer
    update_packetheader(nut, bc, 0);
231
    
232 3aa180b8 Alex Beregszaszi
    /* stream headers */
233
    for (i = 0; i < s->nb_streams; i++)
234
    {
235
        codec = &s->streams[i]->codec;
236
        
237 203504d9 Michael Niedermayer
        put_packetheader(nut, bc, 120);
238 3ac8749b Michael Niedermayer
        put_be64(bc, STREAM_STARTCODE);
239 3aa180b8 Alex Beregszaszi
        put_v(bc, s->streams[i]->index);
240
        put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0);
241
        if (codec->codec_tag)
242 3ac8749b Michael Niedermayer
            put_b(bc, &codec->codec_tag, 4);
243 3aa180b8 Alex Beregszaszi
        else if (codec->codec_type == CODEC_TYPE_VIDEO)
244
        {
245
            int tmp = codec_get_bmp_tag(codec->codec_id);
246
            put_b(bc, &tmp, 4);
247
//            put_v(bc, 4); /* len */
248 3ac8749b Michael Niedermayer
//            put_be32(bc, codec_get_bmp_tag(codec->codec_id));
249 3aa180b8 Alex Beregszaszi
        }
250
        else if (codec->codec_type == CODEC_TYPE_AUDIO)
251
        {
252
            int tmp = codec_get_wav_tag(codec->codec_id);
253
            put_b(bc, &tmp, 4);
254
//            put_v(bc, 4); /* len */
255 3ac8749b Michael Niedermayer
//            put_be32(bc, codec_get_wav_tag(codec->codec_id));
256 3aa180b8 Alex Beregszaszi
        }
257
        put_v(bc, codec->bit_rate);
258
        put_v(bc, 0); /* no language code */
259
        put_v(bc, codec->frame_rate_base);
260
        put_v(bc, codec->frame_rate);
261
        put_v(bc, 0); /* timestamp_shift */
262
        put_v(bc, 0); /* shuffle type */
263
        put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
264
        
265
        put_v(bc, 0); /* no codec specific headers */
266
        
267
        switch(codec->codec_type)
268
        {
269
            case CODEC_TYPE_AUDIO:
270
                put_v(bc, codec->sample_rate / (double)(codec->frame_rate_base / codec->frame_rate));
271
                put_v(bc, codec->channels);
272 3ac8749b Michael Niedermayer
                put_be32(bc, 0); /* FIXME: checksum */
273 3aa180b8 Alex Beregszaszi
                break;
274
            case CODEC_TYPE_VIDEO:
275
                put_v(bc, codec->width);
276
                put_v(bc, codec->height);
277
                put_v(bc, 0); /* aspected w */
278
                put_v(bc, 0); /* aspected h */
279
                put_v(bc, 0); /* csp type -- unknown */
280 3ac8749b Michael Niedermayer
                put_be32(bc, 0); /* FIXME: checksum */
281 3aa180b8 Alex Beregszaszi
                break;
282
        }
283 203504d9 Michael Niedermayer
        update_packetheader(nut, bc, 0);
284 3aa180b8 Alex Beregszaszi
    }
285
286
#if 0
287
    /* info header */
288
    put_packetheader(nut, bc, 16+strlen(s->author)+strlen(s->title)+
289 203504d9 Michael Niedermayer
        strlen(s->comment)+strlen(s->copyright)); 
290 3ac8749b Michael Niedermayer
    put_be64(bc, INFO_STARTCODE);
291 3aa180b8 Alex Beregszaszi
    if (s->author[0])
292
    {
293
        put_v(bc, 5); /* type */
294
        put_b(bc, s->author, strlen(s->author));
295
    }
296
    if (s->title[0])
297
    {
298
        put_v(bc, 6); /* type */
299
        put_b(bc, s->title, strlen(s->title));
300
    }
301
    if (s->comment[0])
302
    {
303
        put_v(bc, 7); /* type */
304
        put_b(bc, s->comment, strlen(s->comment));
305
    }
306
    if (s->copyright[0])
307
    {
308
        put_v(bc, 8); /* type */
309
        put_b(bc, s->copyright, strlen(s->copyright));
310
    }
311
    /* encoder */
312
    put_v(bc, 9); /* type */
313
    put_b(bc, LIBAVFORMAT_IDENT, strlen(LIBAVFORMAT_IDENT));
314

315 3ac8749b Michael Niedermayer
    put_be32(bc, 0); /* FIXME: checksum */
316 203504d9 Michael Niedermayer
    update_packetheader(nut, bc, 0);
317 3aa180b8 Alex Beregszaszi
#endif
318
        
319
    put_flush_packet(bc);
320
    
321
    return 0;
322
}
323
324
static int nut_write_packet(AVFormatContext *s, int stream_index, 
325
                            uint8_t *buf, int size, int force_pts)
326
{
327
    NUTContext *nut = s->priv_data;
328
    ByteIOContext *bc = &s->pb;
329
    int key_frame = 0;
330 3ac8749b Michael Niedermayer
    int flags, size2;
331 3aa180b8 Alex Beregszaszi
    AVCodecContext *enc;
332
333
    if (stream_index > s->nb_streams)
334
        return 1;
335
336
    enc = &s->streams[stream_index]->codec;
337
    if (enc->codec_type == CODEC_TYPE_VIDEO)
338
        key_frame = enc->coded_frame->key_frame;
339
340 203504d9 Michael Niedermayer
    put_packetheader(nut, bc, size+(key_frame?8:0)+20);
341 3aa180b8 Alex Beregszaszi
342
    if (key_frame)
343 3ac8749b Michael Niedermayer
        put_be64(bc, KEYFRAME_STARTCODE);
344
    
345
    flags=0;
346
    flags<<=2; flags|=1; //priority
347
    flags<<=1; flags|=0; //checksum
348
    flags<<=1; flags|=0; //msb_timestamp_flag
349
    flags<<=2; flags|=1; //subpacket_type
350
    flags<<=1; flags|=0; //reserved
351
352
    put_byte(bc, flags);
353 3aa180b8 Alex Beregszaszi
    put_v(bc, stream_index);
354
    put_s(bc, 0); /* lsb_timestamp */
355 203504d9 Michael Niedermayer
    update_packetheader(nut, bc, size);
356 3aa180b8 Alex Beregszaszi
    
357
    put_buffer(bc, buf, size);
358
    
359
    put_flush_packet(bc);
360
361
    return 0;
362
}
363
364
static int nut_write_trailer(AVFormatContext *s)
365
{
366
    NUTContext *nut = s->priv_data;
367
    ByteIOContext *bc = &s->pb;
368
#if 0
369
    int i;
370

371
    /* WRITE INDEX */
372

373
    for (i = 0; s->nb_streams; i++)
374
    {
375 203504d9 Michael Niedermayer
        put_packetheader(nut, bc, 64);
376 3ac8749b Michael Niedermayer
        put_be64(bc, INDEX_STARTCODE);
377 3aa180b8 Alex Beregszaszi
        put_v(bc, s->streams[i]->id);
378
        put_v(bc, ...);
379 3ac8749b Michael Niedermayer
        put_be32(bc, 0); /* FIXME: checksum */
380 203504d9 Michael Niedermayer
        update_packetheader(nut, bc, 0);
381 3aa180b8 Alex Beregszaszi
    }
382
#endif
383
384
    put_flush_packet(bc);
385
386
    return 0;
387
}
388
389
static int nut_probe(AVProbeData *p)
390
{
391 3ac8749b Michael Niedermayer
    int i;
392
    uint64_t code;
393
394
    code = 0xff;
395
    for (i = 0; i < p->buf_size; i++) {
396
        int c = p->buf[i];
397
        code = (code << 8) | c;
398
        code &= 0xFFFFFFFFFFFFFFFFULL;
399
        if (code == MAIN_STARTCODE)
400
            return AVPROBE_SCORE_MAX;
401
    }
402
    return 0;
403 3aa180b8 Alex Beregszaszi
}
404
405
static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
406
{
407
    NUTContext *nut = s->priv_data;
408
    ByteIOContext *bc = &s->pb;
409 3ac8749b Michael Niedermayer
    uint64_t tmp;
410 3aa180b8 Alex Beregszaszi
    int cur_stream, nb_streams;
411
    
412
    /* main header */
413
    get_packetheader(nut, bc);
414 3ac8749b Michael Niedermayer
    tmp = get_be64(bc);
415
    if (tmp != MAIN_STARTCODE)
416
        fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
417 3aa180b8 Alex Beregszaszi
    
418
    tmp = get_v(bc);
419
    if (tmp != 0)
420 3ac8749b Michael Niedermayer
        fprintf(stderr, "bad version (%Ld)\n", tmp);
421 3aa180b8 Alex Beregszaszi
    
422
    nb_streams = get_v(bc);
423
    
424
    s->file_size = get_v(bc);
425
    s->duration = get_v(bc) / (AV_TIME_BASE / 1000);
426
427 3ac8749b Michael Niedermayer
    get_be32(bc); /* checkusm */
428 3aa180b8 Alex Beregszaszi
    
429
    s->bit_rate = 0;
430
    
431
    /* stream header */
432
    for (cur_stream = 0; cur_stream < nb_streams; cur_stream++)
433
    {
434
        int class;
435
        AVStream *st;
436
        
437
        get_packetheader(nut, bc);
438 3ac8749b Michael Niedermayer
        tmp = get_be64(bc);
439
        if (tmp != STREAM_STARTCODE)
440
            fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
441 3aa180b8 Alex Beregszaszi
        st = av_new_stream(s, get_v(bc));
442
        if (!st)
443
            return AVERROR_NOMEM;
444
        class = get_v(bc);
445
        switch(class)
446
        {
447
            case 0:
448
                st->codec.codec_type = CODEC_TYPE_VIDEO;
449
//                get_v(bc);
450 3ac8749b Michael Niedermayer
//                tmp = get_be32(bc);
451
                get_b(bc, (char*)&tmp, 4);
452 3aa180b8 Alex Beregszaszi
                st->codec.codec_id = codec_get_bmp_id(tmp);
453
                if (st->codec.codec_id == CODEC_ID_NONE)
454
                    fprintf(stderr, "Unknown codec?!\n");
455
                break;
456
            case 32:
457
                st->codec.codec_type = CODEC_TYPE_AUDIO;
458
//                tmp = get_v(bc);
459 3ac8749b Michael Niedermayer
//                tmp = get_be32(bc);
460
                get_b(bc, (char*)&tmp, 4);
461 3aa180b8 Alex Beregszaszi
                st->codec.codec_id = codec_get_wav_id(tmp);
462
                if (st->codec.codec_id == CODEC_ID_NONE)
463
                    fprintf(stderr, "Unknown codec?!\n");
464
                break;
465
            default:
466
                fprintf(stderr, "Unknown stream class (%d)\n", class);
467
                return -1;
468
        }
469
        s->bit_rate += get_v(bc);
470
        tmp = get_v(bc); /* language code */
471
        while(tmp--)
472
            get_byte(bc);
473
        st->codec.frame_rate_base = get_v(bc);
474
        st->codec.frame_rate = get_v(bc);
475
        get_v(bc); /* FIXME: msb timestamp base */
476
        get_v(bc); /* shuffle type */
477
        get_byte(bc); /* flags */
478
        
479
        get_v(bc); /* FIXME: codec specific data headers */
480
        
481
        if (class == 0) /* VIDEO */
482
        {
483
            st->codec.width = get_v(bc);
484
            st->codec.height = get_v(bc);
485
            get_v(bc); /* aspected w */
486
            get_v(bc); /* aspected h */
487
            get_v(bc); /* csp type */
488
            get_le32(bc); /* checksum */
489
        }
490
        if (class == 32) /* AUDIO */
491
        {
492
            st->codec.sample_rate = get_v(bc) * (double)(st->codec.frame_rate_base / st->codec.frame_rate);
493
            st->codec.channels = get_v(bc);
494
            get_le32(bc); /* checksum */
495
        }
496
    }    
497
    
498
    return 0;
499
}
500
501
static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
502
{
503
    NUTContext *nut = s->priv_data;
504
    ByteIOContext *bc = &s->pb;
505 3ac8749b Michael Niedermayer
    int id, timestamp, size;
506 3aa180b8 Alex Beregszaszi
    int key_frame = 0;
507 3ac8749b Michael Niedermayer
    uint64_t tmp;
508 3aa180b8 Alex Beregszaszi
509
    get_packetheader(nut, bc);
510
511
    if (url_feof(bc))
512
        return -1;
513
    
514
    tmp = get_byte(bc);
515 3ac8749b Michael Niedermayer
    if (tmp & 0x80) /* zero bit set? */
516 3aa180b8 Alex Beregszaszi
    {
517 3ac8749b Michael Niedermayer
        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 3aa180b8 Alex Beregszaszi
        {
522
            key_frame = 1;
523
            tmp = get_byte(bc); /* flags */
524
        }
525
        else
526 3ac8749b Michael Niedermayer
            fprintf(stderr, "error in zero bit / startcode %LX\n", tmp);
527 3aa180b8 Alex Beregszaszi
    }
528 3ac8749b Michael Niedermayer
#if 0
529
    if (((tmp & 0x60)>>5) > 3) /* priority <= 3 */
530 3aa180b8 Alex Beregszaszi
        fprintf(stderr, "sanity check failed!\n");
531 3ac8749b Michael Niedermayer
#endif
532 3aa180b8 Alex Beregszaszi
    id = get_v(bc);
533
    timestamp = get_s(bc);
534
    
535
    size = (nut->curr_frame_size - (url_ftell(bc)-nut->curr_frame_start));
536 3ac8749b Michael Niedermayer
    dprintf("flags: 0x%Lx, timestamp: %d, packet size: %d\n", tmp, timestamp, size);
537 3aa180b8 Alex Beregszaszi
    
538
    if (size < 0)
539
        return -1;
540
541
    av_new_packet(pkt, size);
542
    get_buffer(bc, pkt->data, size);
543
    pkt->stream_index = id;
544
    if (key_frame)
545
        pkt->flags |= PKT_FLAG_KEY;
546
    pkt->pts = timestamp;
547
548
    return 0;
549
}
550
551
static AVInputFormat nut_iformat = {
552
    "nut",
553
    "nut format",
554
    sizeof(NUTContext),
555
    nut_probe,
556
    nut_read_header,
557
    nut_read_packet,
558
//    nut_read_close,
559
//    nut_read_seek,
560
    .extensions = "nut",
561
};
562
563
static AVOutputFormat nut_oformat = {
564
    "nut",
565
    "nut format",
566
    "video/x-nut",
567
    "nut",
568
    sizeof(NUTContext),
569
#ifdef CONFIG_VORBIS
570
    CODEC_ID_VORBIS,
571
#elif defined(CONFIG_MP3LAME)
572
    CODEC_ID_MP3LAME,
573
#else
574
    CODEC_ID_MP2,
575
#endif
576
    CODEC_ID_MPEG4,
577
    nut_write_header,
578
    nut_write_packet,
579
    nut_write_trailer,
580
};
581
582
int nut_init(void)
583
{
584
    av_register_input_format(&nut_iformat);
585
    av_register_output_format(&nut_oformat);
586
    return 0;
587
}