Statistics
| Branch: | Revision:

ffmpeg / libavformat / nut.c @ 99b17f25

History | View | Annotate | Download (13.8 KB)

1
/*
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
//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
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
/**
117
 * 
118
 */
119
static int get_length(uint64_t val){
120
    int i;
121

    
122
    for (i=7; ; i+=7)
123
        if ((val>>i) == 0)
124
            return i;
125

    
126
    return 7; //not reached
127
}
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
    i= get_length(val);
141

    
142
    for (i-=7; i>0; i-=7){
143
        put_byte(bc, 0x80 | (val>>i));
144
    }
145

    
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
static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size)
171
{
172
    put_flush_packet(bc);
173
    nut->curr_frame_start = url_ftell(bc);
174
    nut->curr_frame_size = max_size;
175
    
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
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
    
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
    put_packetheader(nut, bc, 120);
221
    
222
    /* main header */
223
    put_be64(bc, MAIN_STARTCODE);
224
    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
    put_be32(bc, 0); /* FIXME: checksum */
229
    
230
    update_packetheader(nut, bc, 0);
231
    
232
    /* stream headers */
233
    for (i = 0; i < s->nb_streams; i++)
234
    {
235
        codec = &s->streams[i]->codec;
236
        
237
        put_packetheader(nut, bc, 120);
238
        put_be64(bc, STREAM_STARTCODE);
239
        put_v(bc, i /*s->streams[i]->index*/);
240
        put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0);
241
        if (codec->codec_tag)
242
            put_b(bc, &codec->codec_tag, 4);
243
        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
//            put_be32(bc, codec_get_bmp_tag(codec->codec_id));
249
        }
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
//            put_be32(bc, codec_get_wav_tag(codec->codec_id));
256
        }
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
                put_be32(bc, 0); /* FIXME: checksum */
273
                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
                put_be32(bc, 0); /* FIXME: checksum */
281
                break;
282
        }
283
        update_packetheader(nut, bc, 0);
284
    }
285

    
286
#if 0
287
    /* info header */
288
    put_packetheader(nut, bc, 16+strlen(s->author)+strlen(s->title)+
289
        strlen(s->comment)+strlen(s->copyright)); 
290
    put_be64(bc, INFO_STARTCODE);
291
    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 "\0", strlen(LIBAVFORMAT_IDENT));
314
    
315
    put_v(bc, 0); /* eof info */
316

317
    put_be32(bc, 0); /* FIXME: checksum */
318
    update_packetheader(nut, bc, 0);
319
#endif
320
        
321
    put_flush_packet(bc);
322
    
323
    return 0;
324
}
325

    
326
static int nut_write_packet(AVFormatContext *s, int stream_index, 
327
                            uint8_t *buf, int size, int force_pts)
328
{
329
    NUTContext *nut = s->priv_data;
330
    ByteIOContext *bc = &s->pb;
331
    int key_frame = 0;
332
    int flags, size2;
333
    AVCodecContext *enc;
334

    
335
    if (stream_index > s->nb_streams)
336
        return 1;
337

    
338
    enc = &s->streams[stream_index]->codec;
339
    if (enc->codec_type == CODEC_TYPE_VIDEO)
340
        key_frame = enc->coded_frame->key_frame;
341

    
342
    put_packetheader(nut, bc, size+(key_frame?8:0)+20);
343

    
344
    if (key_frame)
345
        put_be64(bc, KEYFRAME_STARTCODE);
346
    
347
    flags=0;
348
    flags<<=2; flags|=1; //priority
349
    flags<<=1; flags|=0; //checksum
350
    flags<<=1; flags|=0; //msb_timestamp_flag
351
    flags<<=2; flags|=1; //subpacket_type
352
    flags<<=1; flags|=0; //reserved
353

    
354
    put_byte(bc, flags);
355
    put_v(bc, stream_index);
356
    put_s(bc, force_pts); /* lsb_timestamp */
357
    update_packetheader(nut, bc, size);
358
    
359
    put_buffer(bc, buf, size);
360
    
361
    put_flush_packet(bc);
362

    
363
    return 0;
364
}
365

    
366
static int nut_write_trailer(AVFormatContext *s)
367
{
368
    NUTContext *nut = s->priv_data;
369
    ByteIOContext *bc = &s->pb;
370
#if 0
371
    int i;
372

373
    /* WRITE INDEX */
374

375
    for (i = 0; s->nb_streams; i++)
376
    {
377
        put_packetheader(nut, bc, 64);
378
        put_be64(bc, INDEX_STARTCODE);
379
        put_v(bc, s->streams[i]->id);
380
        put_v(bc, ...);
381
        put_be32(bc, 0); /* FIXME: checksum */
382
        update_packetheader(nut, bc, 0);
383
    }
384
#endif
385

    
386
    put_flush_packet(bc);
387

    
388
    return 0;
389
}
390

    
391
static int nut_probe(AVProbeData *p)
392
{
393
    int i;
394
    uint64_t code;
395

    
396
    code = 0xff;
397
    for (i = 0; i < p->buf_size; i++) {
398
        int c = p->buf[i];
399
        code = (code << 8) | c;
400
        code &= 0xFFFFFFFFFFFFFFFFULL;
401
        if (code == MAIN_STARTCODE)
402
            return AVPROBE_SCORE_MAX;
403
    }
404
    return 0;
405
}
406

    
407
static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
408
{
409
    NUTContext *nut = s->priv_data;
410
    ByteIOContext *bc = &s->pb;
411
    uint64_t tmp;
412
    int cur_stream, nb_streams;
413
    
414
    /* main header */
415
    get_packetheader(nut, bc);
416
    tmp = get_be64(bc);
417
    if (tmp != MAIN_STARTCODE)
418
        fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
419
    
420
    tmp = get_v(bc);
421
    if (tmp != 0)
422
        fprintf(stderr, "bad version (%Ld)\n", tmp);
423
    
424
    nb_streams = get_v(bc);
425
    
426
    s->file_size = get_v(bc);
427
    s->duration = get_v(bc) / (AV_TIME_BASE / 1000);
428

    
429
    get_be32(bc); /* checkusm */
430
    
431
    s->bit_rate = 0;
432
    
433
    /* stream header */
434
    for (cur_stream = 0; cur_stream < nb_streams; cur_stream++)
435
    {
436
        int class;
437
        AVStream *st;
438
        
439
        get_packetheader(nut, bc);
440
        tmp = get_be64(bc);
441
        if (tmp != STREAM_STARTCODE)
442
            fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
443
        st = av_new_stream(s, get_v(bc));
444
        if (!st)
445
            return AVERROR_NOMEM;
446
        class = get_v(bc);
447
        switch(class)
448
        {
449
            case 0:
450
                st->codec.codec_type = CODEC_TYPE_VIDEO;
451
//                get_v(bc);
452
//                tmp = get_be32(bc);
453
                get_b(bc, (char*)&tmp, 4);
454
                st->codec.codec_id = codec_get_bmp_id(tmp);
455
                if (st->codec.codec_id == CODEC_ID_NONE)
456
                    fprintf(stderr, "Unknown codec?!\n");
457
                break;
458
            case 32:
459
                st->codec.codec_type = CODEC_TYPE_AUDIO;
460
//                tmp = get_v(bc);
461
//                tmp = get_be32(bc);
462
                get_b(bc, (char*)&tmp, 4);
463
                st->codec.codec_id = codec_get_wav_id(tmp);
464
                if (st->codec.codec_id == CODEC_ID_NONE)
465
                    fprintf(stderr, "Unknown codec?!\n");
466
                break;
467
            default:
468
                fprintf(stderr, "Unknown stream class (%d)\n", class);
469
                return -1;
470
        }
471
        s->bit_rate += get_v(bc);
472
        tmp = get_v(bc); /* language code */
473
        while(tmp--)
474
            get_byte(bc);
475
        st->codec.frame_rate_base = get_v(bc);
476
        st->codec.frame_rate = get_v(bc);
477
        get_v(bc); /* FIXME: msb timestamp base */
478
        get_v(bc); /* shuffle type */
479
        get_byte(bc); /* flags */
480
        
481
        get_v(bc); /* FIXME: codec specific data headers */
482
        
483
        if (class == 0) /* VIDEO */
484
        {
485
            st->codec.width = get_v(bc);
486
            st->codec.height = get_v(bc);
487
            get_v(bc); /* aspected w */
488
            get_v(bc); /* aspected h */
489
            get_v(bc); /* csp type */
490
            get_le32(bc); /* checksum */
491
        }
492
        if (class == 32) /* AUDIO */
493
        {
494
            st->codec.sample_rate = get_v(bc) * (double)(st->codec.frame_rate_base / st->codec.frame_rate);
495
            st->codec.channels = get_v(bc);
496
            get_le32(bc); /* checksum */
497
        }
498
    }    
499
    
500
    return 0;
501
}
502

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

    
511
    get_packetheader(nut, bc);
512

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

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

    
550
    return 0;
551
}
552

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

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

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