Statistics
| Branch: | Revision:

ffmpeg / libavformat / nut.c @ a182f5da

History | View | Annotate | Download (13.6 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)
90
{
91
    int i, len, val;
92
    
93
    len = get_v(bc);
94
    val = 0;
95
    for (i = 0; i < len; i++) {
96
        if (i < 4)
97
            val |= get_byte(bc) << (i * 8);
98
    }
99
    return val;
100
}
101

    
102
static int get_packetheader(NUTContext *nut, ByteIOContext *bc)
103
{
104
    nut->curr_frame_start = url_ftell(bc);
105
    nut->curr_frame_size = get_v(bc);
106
    nut->last_frame_size = get_v(bc);
107
    dprintf("Packet: fwd: %d bwd: %d\n",
108
        nut->curr_frame_size, nut->last_frame_size);
109
    
110
    return 0;
111
}
112

    
113
/**
114
 * 
115
 */
116
static int get_length(uint64_t val){
117
    int i;
118

    
119
    for (i=7; ; i+=7)
120
        if ((val>>i) == 0)
121
            return i;
122

    
123
    return 7; //not reached
124
}
125

    
126
static int put_v(ByteIOContext *bc, uint64_t val)
127
{
128
    int i;
129

    
130
//    if (bytes_left(s)*8 < 9)
131
//        return -1;
132

    
133
    if (bytes_left(bc) < 1)
134
        return -1;
135

    
136
    val &= 0x7FFFFFFFFFFFFFFFULL; // FIXME can only encode upto 63 bits currently
137
    i= get_length(val);
138

    
139
    for (i-=7; i>0; i-=7){
140
        put_byte(bc, 0x80 | (val>>i));
141
    }
142

    
143
    put_byte(bc, val&0x7f);
144

    
145
    return 0;
146
}
147

    
148
static int put_s(ByteIOContext *bc, uint64_t val)
149
{
150
    if (val<=0)
151
        return put_v(bc, -2*val);
152
    else
153
        return put_v(bc, 2*val-1);
154
}
155

    
156
static int put_b(ByteIOContext *bc, char *data, int len)
157
{
158
    int i;
159
    
160
    put_v(bc, len);
161
    for (i = 0; i < len; i++)
162
        put_byte(bc, data[i]);
163

    
164
    return 0;
165
}
166

    
167
static int put_bi(ByteIOContext *bc, int val)
168
{
169
    put_v(bc, 4);
170
    put_le32(bc, val);
171
    return 0;
172
}
173

    
174
static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size)
175
{
176
    put_flush_packet(bc);
177
    nut->curr_frame_start = url_ftell(bc);
178
    nut->curr_frame_size = max_size;
179
    
180
    /* packet header */
181
    put_v(bc, nut->curr_frame_size); /* forward ptr */
182
    put_v(bc, nut->last_frame_size); /* backward ptr */
183
    dprintf("Packet: fwd: %d, bwd: %d\n",
184
        nut->curr_frame_size, nut->last_frame_size);
185

    
186
    nut->last_frame_size = nut->curr_frame_size;
187
    
188
    return 0;
189
}
190

    
191
static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size){
192
    offset_t start= nut->curr_frame_start;
193
    offset_t cur= url_ftell(bc);
194
    int size= cur - start + additional_size;
195
    
196
    assert( size <= nut->curr_frame_size );
197
    
198
    url_fseek(bc, start, SEEK_SET);
199
    put_v(bc, size);
200
    if(get_length(size) < get_length(nut->curr_frame_size))
201
        put_byte(bc, 0x80);
202
    nut->curr_frame_size= size;
203
    dprintf("Packet update: size: %d\n", size);
204

    
205
    url_fseek(bc, cur, SEEK_SET);    
206
    
207
    return 0;
208
}
209

    
210
static int nut_write_header(AVFormatContext *s)
211
{
212
    NUTContext *nut = s->priv_data;
213
    ByteIOContext *bc = &s->pb;
214
    AVCodecContext *codec;
215
    int i;
216
    int stream_length = 0;
217

    
218
    for (i = 0; i < s->nb_streams; i++)
219
    {
220
        if (stream_length < (s->streams[i]->duration * (AV_TIME_BASE / 1000)))
221
            stream_length = s->streams[i]->duration * (AV_TIME_BASE / 1000);
222
    }
223

    
224
    /* main header */
225
    put_be64(bc, MAIN_STARTCODE);
226
    put_packetheader(nut, bc, 120);
227
    put_v(bc, 0); /* version */
228
    put_v(bc, s->nb_streams);
229
    put_v(bc, 0); /* file size */
230
    put_v(bc, stream_length); /* len in msec */
231
    put_be32(bc, 0); /* FIXME: checksum */
232
    
233
    update_packetheader(nut, bc, 0);
234
    
235
    /* stream headers */
236
    for (i = 0; i < s->nb_streams; i++)
237
    {
238
        codec = &s->streams[i]->codec;
239
        
240
        put_be64(bc, STREAM_STARTCODE);
241
        put_packetheader(nut, bc, 120);
242
        put_v(bc, i /*s->streams[i]->index*/);
243
        put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0);
244
        if (codec->codec_tag)
245
            put_bi(bc, codec->codec_tag);
246
        else if (codec->codec_type == CODEC_TYPE_VIDEO)
247
        {
248
            int tmp = codec_get_bmp_tag(codec->codec_id);
249
            put_bi(bc, tmp);
250
        }
251
        else if (codec->codec_type == CODEC_TYPE_AUDIO)
252
        {
253
            int tmp = codec_get_wav_tag(codec->codec_id);
254
            put_bi(bc, tmp);
255
        }
256
        put_v(bc, codec->bit_rate);
257
        put_v(bc, 0); /* no language code */
258
        put_v(bc, codec->frame_rate_base);
259
        put_v(bc, codec->frame_rate);
260
        put_v(bc, 0); /* timestamp_shift */
261
        put_v(bc, 0); /* shuffle type */
262
        put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
263
        
264
        put_v(bc, 0); /* no codec specific headers */
265
        
266
        switch(codec->codec_type)
267
        {
268
            case CODEC_TYPE_AUDIO:
269
                put_v(bc, codec->sample_rate / (double)(codec->frame_rate_base / codec->frame_rate));
270
                put_v(bc, codec->channels);
271
                put_be32(bc, 0); /* FIXME: checksum */
272
                break;
273
            case CODEC_TYPE_VIDEO:
274
                put_v(bc, codec->width);
275
                put_v(bc, codec->height);
276
                put_v(bc, 0); /* aspected w */
277
                put_v(bc, 0); /* aspected h */
278
                put_v(bc, 0); /* csp type -- unknown */
279
                put_be32(bc, 0); /* FIXME: checksum */
280
                break;
281
            default:
282
                break;
283
        }
284
        update_packetheader(nut, bc, 0);
285
    }
286

    
287
#if 0
288
    /* info header */
289
    put_be64(bc, INFO_STARTCODE);
290
    put_packetheader(nut, bc, 16+strlen(s->author)+strlen(s->title)+
291
        strlen(s->comment)+strlen(s->copyright)); 
292
    if (s->author[0])
293
    {
294
        put_v(bc, 5); /* type */
295
        put_b(bc, s->author, strlen(s->author));
296
    }
297
    if (s->title[0])
298
    {
299
        put_v(bc, 6); /* type */
300
        put_b(bc, s->title, strlen(s->title));
301
    }
302
    if (s->comment[0])
303
    {
304
        put_v(bc, 7); /* type */
305
        put_b(bc, s->comment, strlen(s->comment));
306
    }
307
    if (s->copyright[0])
308
    {
309
        put_v(bc, 8); /* type */
310
        put_b(bc, s->copyright, strlen(s->copyright));
311
    }
312
    /* encoder */
313
    put_v(bc, 9); /* type */
314
    put_b(bc, LIBAVFORMAT_IDENT "\0", strlen(LIBAVFORMAT_IDENT));
315
    
316
    put_v(bc, 0); /* eof info */
317

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

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

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

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

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

    
353
    put_byte(bc, flags);
354

    
355
    put_packetheader(nut, bc, size+20);
356
    put_v(bc, stream_index);
357
    put_s(bc, force_pts); /* lsb_timestamp */
358
    update_packetheader(nut, bc, size);
359
    
360
    put_buffer(bc, buf, size);
361
    
362
    put_flush_packet(bc);
363

    
364
    return 0;
365
}
366

    
367
static int nut_write_trailer(AVFormatContext *s)
368
{
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_be64(bc, INDEX_STARTCODE);
378
        put_packetheader(nut, bc, 64);
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
    tmp = get_be64(bc);
416
    if (tmp != MAIN_STARTCODE)
417
        fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
418
    get_packetheader(nut, bc);
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
        tmp = get_be64(bc);
440
        if (tmp != STREAM_STARTCODE)
441
            fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
442
        get_packetheader(nut, bc);
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
                tmp = get_b(bc);
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_b(bc);
459
                st->codec.codec_id = codec_get_wav_id(tmp);
460
                if (st->codec.codec_id == CODEC_ID_NONE)
461
                    fprintf(stderr, "Unknown codec?!\n");
462
                break;
463
            default:
464
                fprintf(stderr, "Unknown stream class (%d)\n", class);
465
                return -1;
466
        }
467
        s->bit_rate += get_v(bc);
468
        tmp = get_v(bc); /* language code */
469
        while(tmp--)
470
            get_byte(bc);
471
        st->codec.frame_rate_base = get_v(bc);
472
        st->codec.frame_rate = get_v(bc);
473
        get_v(bc); /* FIXME: msb timestamp base */
474
        get_v(bc); /* shuffle type */
475
        get_byte(bc); /* flags */
476
        
477
        get_v(bc); /* FIXME: codec specific data headers */
478
        
479
        if (class == 0) /* VIDEO */
480
        {
481
            st->codec.width = get_v(bc);
482
            st->codec.height = get_v(bc);
483
            get_v(bc); /* aspected w */
484
            get_v(bc); /* aspected h */
485
            get_v(bc); /* csp type */
486
            get_le32(bc); /* checksum */
487
        }
488
        if (class == 32) /* AUDIO */
489
        {
490
            st->codec.sample_rate = get_v(bc) * (double)(st->codec.frame_rate_base / st->codec.frame_rate);
491
            st->codec.channels = get_v(bc);
492
            get_le32(bc); /* checksum */
493
        }
494
    }    
495
    
496
    return 0;
497
}
498

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

    
507

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

    
539
    av_new_packet(pkt, size);
540
    get_buffer(bc, pkt->data, size);
541
    pkt->stream_index = id;
542
    if (key_frame)
543
        pkt->flags |= PKT_FLAG_KEY;
544
    pkt->pts = timestamp;
545

    
546
    return 0;
547
}
548

    
549
static AVInputFormat nut_iformat = {
550
    "nut",
551
    "nut format",
552
    sizeof(NUTContext),
553
    nut_probe,
554
    nut_read_header,
555
    nut_read_packet,
556
//    nut_read_close,
557
//    nut_read_seek,
558
    .extensions = "nut",
559
};
560

    
561
static AVOutputFormat nut_oformat = {
562
    "nut",
563
    "nut format",
564
    "video/x-nut",
565
    "nut",
566
    sizeof(NUTContext),
567
#ifdef CONFIG_VORBIS
568
    CODEC_ID_VORBIS,
569
#elif defined(CONFIG_MP3LAME)
570
    CODEC_ID_MP3LAME,
571
#else
572
    CODEC_ID_MP2, /* AC3 needs liba52 decoder */
573
#endif
574
    CODEC_ID_MPEG4,
575
    nut_write_header,
576
    nut_write_packet,
577
    nut_write_trailer,
578
};
579

    
580
int nut_init(void)
581
{
582
    av_register_input_format(&nut_iformat);
583
    av_register_output_format(&nut_oformat);
584
    return 0;
585
}