Statistics
| Branch: | Revision:

ffmpeg / libavformat / nut.c @ 8c653280

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
#include "avi.h"
42

    
43
//from /dev/random
44

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

    
51
typedef struct {
52
    int curr_frame_start;
53
    int last_frame_size;
54
    int curr_frame_size;
55
} NUTContext;
56

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

    
62
static uint64_t get_v(ByteIOContext *bc)
63
{
64
    uint64_t val = 0;
65

    
66
//    for (; bytes_left(s)*8 > 0; )
67
    for(; bytes_left(bc) > 0; )
68
    {
69
        int tmp = get_byte(bc);
70

    
71
        if (tmp&0x80)
72
            val= (val<<7) + tmp - 0x80;
73
        else
74
            return (val<<7) + tmp;
75
    }
76
    return -1;
77
}
78

    
79
static int64_t get_s(ByteIOContext *bc)
80
{
81
    int64_t v = get_v(bc) + 1;
82

    
83
    if (v&1)
84
        return -(v>>1);
85
    else
86
        return (v>>1);
87
}
88

    
89
static int get_b(ByteIOContext *bc, char *data, int maxlen)
90
{
91
    int i, len;
92
    
93
    len = get_v(bc);
94
    for (i = 0; i < len && i < maxlen; i++)
95
        data[i] = get_byte(bc);
96
    if (i < len)
97
    {
98
        len = i;
99
        for (i = 0; i < len; i++)
100
            get_byte(bc);
101
    }
102

    
103
    return 0;
104
}
105

    
106
static int get_bi(ByteIOContext *bc)
107
{
108
   int i, len, val;
109
    
110
    len = get_v(bc);
111
    if(len > 4) return -1;
112
    
113
    val = 0;
114
    for (i = 0; i < len; i++) {
115
        val |= get_byte(bc) << (i * 8);
116
    }
117

    
118
    return val;
119
}
120

    
121
static int get_packetheader(NUTContext *nut, ByteIOContext *bc)
122
{
123
    nut->curr_frame_start = url_ftell(bc);
124
    nut->curr_frame_size = get_v(bc);
125
    nut->last_frame_size = get_v(bc);
126
    dprintf("Packet: fwd: %d bwd: %d\n",
127
        nut->curr_frame_size, nut->last_frame_size);
128
    
129
    return 0;
130
}
131

    
132
/**
133
 * 
134
 */
135
static int get_length(uint64_t val){
136
    int i;
137

    
138
    for (i=7; ; i+=7)
139
        if ((val>>i) == 0)
140
            return i;
141

    
142
    return 7; //not reached
143
}
144

    
145
static int put_v(ByteIOContext *bc, uint64_t val)
146
{
147
    int i;
148

    
149
//    if (bytes_left(s)*8 < 9)
150
//        return -1;
151

    
152
    if (bytes_left(bc) < 1)
153
        return -1;
154

    
155
    val &= 0x7FFFFFFFFFFFFFFFULL; // FIXME can only encode upto 63 bits currently
156
    i= get_length(val);
157

    
158
    for (i-=7; i>0; i-=7){
159
        put_byte(bc, 0x80 | (val>>i));
160
    }
161

    
162
    put_byte(bc, val&0x7f);
163

    
164
    return 0;
165
}
166

    
167
static int put_s(ByteIOContext *bc, uint64_t val)
168
{
169
    if (val<=0)
170
        return put_v(bc, -2*val);
171
    else
172
        return put_v(bc, 2*val-1);
173
}
174

    
175
static int put_b(ByteIOContext *bc, char *data, int len)
176
{
177
    int i;
178
    
179
    put_v(bc, len);
180
    for (i = 0; i < len; i++)
181
        put_byte(bc, data[i]);
182

    
183
    return 0;
184
}
185

    
186
static int put_bi(ByteIOContext *bc, int val)
187
{
188
    put_v(bc, 4);
189
    put_le32(bc, val);
190
    return 0;
191
}
192

    
193
static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size)
194
{
195
    put_flush_packet(bc);
196
    nut->curr_frame_start = url_ftell(bc);
197
    nut->curr_frame_size = max_size;
198
    
199
    /* packet header */
200
    put_v(bc, nut->curr_frame_size); /* forward ptr */
201
    put_v(bc, nut->last_frame_size); /* backward ptr */
202
    dprintf("Packet: fwd: %d, bwd: %d\n",
203
        nut->curr_frame_size, nut->last_frame_size);
204

    
205
    nut->last_frame_size = nut->curr_frame_size;
206
    
207
    return 0;
208
}
209

    
210
static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size){
211
    offset_t start= nut->curr_frame_start;
212
    offset_t cur= url_ftell(bc);
213
    int size= cur - start + additional_size;
214
    
215
    assert( size <= nut->curr_frame_size );
216
    
217
    url_fseek(bc, start, SEEK_SET);
218
    put_v(bc, size);
219
    if(get_length(size) < get_length(nut->curr_frame_size))
220
        put_byte(bc, 0x80);
221
    nut->curr_frame_size= size;
222
    dprintf("Packet update: size: %d\n", size);
223

    
224
    url_fseek(bc, cur, SEEK_SET);    
225
    
226
    return 0;
227
}
228

    
229
static int nut_write_header(AVFormatContext *s)
230
{
231
    NUTContext *nut = s->priv_data;
232
    ByteIOContext *bc = &s->pb;
233
    AVCodecContext *codec;
234
    int i;
235
    int stream_length = 0;
236

    
237
    for (i = 0; i < s->nb_streams; i++)
238
    {
239
        if (stream_length < (s->streams[i]->duration * (AV_TIME_BASE / 1000)))
240
            stream_length = s->streams[i]->duration * (AV_TIME_BASE / 1000);
241
    }
242

    
243
    /* main header */
244
    put_be64(bc, MAIN_STARTCODE);
245
    put_packetheader(nut, bc, 120);
246
    put_v(bc, 0); /* version */
247
    put_v(bc, s->nb_streams);
248
    put_v(bc, 0); /* file size */
249
    put_v(bc, stream_length); /* len in msec */
250
    put_be32(bc, 0); /* FIXME: checksum */
251
    
252
    update_packetheader(nut, bc, 0);
253
    
254
    /* stream headers */
255
    for (i = 0; i < s->nb_streams; i++)
256
    {
257
        codec = &s->streams[i]->codec;
258
        
259
        put_be64(bc, STREAM_STARTCODE);
260
        put_packetheader(nut, bc, 120);
261
        put_v(bc, i /*s->streams[i]->index*/);
262
        put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0);
263
        if (codec->codec_tag)
264
            put_bi(bc, codec->codec_tag);
265
        else if (codec->codec_type == CODEC_TYPE_VIDEO)
266
        {
267
            int tmp = codec_get_bmp_tag(codec->codec_id);
268
            put_bi(bc, tmp);
269
        }
270
        else if (codec->codec_type == CODEC_TYPE_AUDIO)
271
        {
272
            int tmp = codec_get_wav_tag(codec->codec_id);
273
            put_bi(bc, tmp);
274
        }
275
        put_v(bc, codec->bit_rate);
276
        put_v(bc, 0); /* no language code */
277
        put_v(bc, codec->frame_rate_base);
278
        put_v(bc, codec->frame_rate);
279
        put_v(bc, 0); /* timestamp_shift */
280
        put_v(bc, 0); /* shuffle type */
281
        put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
282
        
283
        put_v(bc, 0); /* no codec specific headers */
284
        
285
        switch(codec->codec_type)
286
        {
287
            case CODEC_TYPE_AUDIO:
288
                put_v(bc, codec->sample_rate / (double)(codec->frame_rate_base / codec->frame_rate));
289
                put_v(bc, codec->channels);
290
                put_be32(bc, 0); /* FIXME: checksum */
291
                break;
292
            case CODEC_TYPE_VIDEO:
293
                put_v(bc, codec->width);
294
                put_v(bc, codec->height);
295
                put_v(bc, 0); /* aspected w */
296
                put_v(bc, 0); /* aspected h */
297
                put_v(bc, 0); /* csp type -- unknown */
298
                put_be32(bc, 0); /* FIXME: checksum */
299
                break;
300
            default:
301
                break;
302
        }
303
        update_packetheader(nut, bc, 0);
304
    }
305

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

337
    put_be32(bc, 0); /* FIXME: checksum */
338
    update_packetheader(nut, bc, 0);
339
#endif
340
        
341
    put_flush_packet(bc);
342
    
343
    return 0;
344
}
345

    
346
static int nut_write_packet(AVFormatContext *s, int stream_index, 
347
                            uint8_t *buf, int size, int force_pts)
348
{
349
    NUTContext *nut = s->priv_data;
350
    ByteIOContext *bc = &s->pb;
351
    int key_frame = 0;
352
    int flags;
353
    AVCodecContext *enc;
354

    
355
    if (stream_index > s->nb_streams)
356
        return 1;
357

    
358
    enc = &s->streams[stream_index]->codec;
359
    key_frame = enc->coded_frame->key_frame;
360

    
361
    if (key_frame)
362
        put_be64(bc, KEYFRAME_STARTCODE);
363
    
364
    flags=0;
365
    flags<<=2; flags|=1; //priority
366
    flags<<=1; flags|=0; //checksum
367
    flags<<=1; flags|=0; //msb_timestamp_flag
368
    flags<<=2; flags|=1; //subpacket_type
369
    flags<<=1; flags|=0; //reserved
370

    
371
    put_byte(bc, flags);
372

    
373
    put_packetheader(nut, bc, size+20);
374
    put_v(bc, stream_index);
375
    put_s(bc, force_pts); /* lsb_timestamp */
376
    update_packetheader(nut, bc, size);
377
    
378
    put_buffer(bc, buf, size);
379
    
380
    put_flush_packet(bc);
381

    
382
    return 0;
383
}
384

    
385
static int nut_write_trailer(AVFormatContext *s)
386
{
387
    ByteIOContext *bc = &s->pb;
388
#if 0
389
    int i;
390

391
    /* WRITE INDEX */
392

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

    
404
    put_flush_packet(bc);
405

    
406
    return 0;
407
}
408

    
409
static int nut_probe(AVProbeData *p)
410
{
411
    int i;
412
    uint64_t code;
413

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

    
424
static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
425
{
426
    NUTContext *nut = s->priv_data;
427
    ByteIOContext *bc = &s->pb;
428
    uint64_t tmp;
429
    int cur_stream, nb_streams;
430
    
431
    /* main header */
432
    tmp = get_be64(bc);
433
    if (tmp != MAIN_STARTCODE)
434
        fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
435
    get_packetheader(nut, bc);
436
    
437
    tmp = get_v(bc);
438
    if (tmp != 0)
439
        fprintf(stderr, "bad version (%Ld)\n", tmp);
440
    
441
    nb_streams = get_v(bc);
442
    
443
    s->file_size = get_v(bc);
444
    s->duration = get_v(bc) / (AV_TIME_BASE / 1000);
445

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

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

    
521

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

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

    
560
    return 0;
561
}
562

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

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

    
594
int nut_init(void)
595
{
596
    av_register_input_format(&nut_iformat);
597
    av_register_output_format(&nut_oformat);
598
    return 0;
599
}