Statistics
| Branch: | Revision:

ffmpeg / libavformat / nut.c @ 203504d9

History | View | Annotate | Download (13.7 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, 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, strlen(LIBAVFORMAT_IDENT));
314

315
    put_be32(bc, 0); /* FIXME: checksum */
316
    update_packetheader(nut, bc, 0);
317
#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
    int flags, size2;
331
    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
    put_packetheader(nut, bc, size+(key_frame?8:0)+20);
341

    
342
    if (key_frame)
343
        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
    put_v(bc, stream_index);
354
    put_s(bc, 0); /* lsb_timestamp */
355
    update_packetheader(nut, bc, size);
356
    
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
        put_packetheader(nut, bc, 64);
376
        put_be64(bc, INDEX_STARTCODE);
377
        put_v(bc, s->streams[i]->id);
378
        put_v(bc, ...);
379
        put_be32(bc, 0); /* FIXME: checksum */
380
        update_packetheader(nut, bc, 0);
381
    }
382
#endif
383

    
384
    put_flush_packet(bc);
385

    
386
    return 0;
387
}
388

    
389
static int nut_probe(AVProbeData *p)
390
{
391
    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
}
404

    
405
static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
406
{
407
    NUTContext *nut = s->priv_data;
408
    ByteIOContext *bc = &s->pb;
409
    uint64_t tmp;
410
    int cur_stream, nb_streams;
411
    
412
    /* main header */
413
    get_packetheader(nut, bc);
414
    tmp = get_be64(bc);
415
    if (tmp != MAIN_STARTCODE)
416
        fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
417
    
418
    tmp = get_v(bc);
419
    if (tmp != 0)
420
        fprintf(stderr, "bad version (%Ld)\n", tmp);
421
    
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
    get_be32(bc); /* checkusm */
428
    
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
        tmp = get_be64(bc);
439
        if (tmp != STREAM_STARTCODE)
440
            fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
441
        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
//                tmp = get_be32(bc);
451
                get_b(bc, (char*)&tmp, 4);
452
                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
//                tmp = get_be32(bc);
460
                get_b(bc, (char*)&tmp, 4);
461
                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
    int id, timestamp, size;
506
    int key_frame = 0;
507
    uint64_t tmp;
508

    
509
    get_packetheader(nut, bc);
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
#if 0
529
    if (((tmp & 0x60)>>5) > 3) /* priority <= 3 */
530
        fprintf(stderr, "sanity check failed!\n");
531
#endif
532
    id = get_v(bc);
533
    timestamp = get_s(bc);
534
    
535
    size = (nut->curr_frame_size - (url_ftell(bc)-nut->curr_frame_start));
536
    dprintf("flags: 0x%Lx, timestamp: %d, packet size: %d\n", tmp, timestamp, size);
537
    
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
}