Statistics
| Branch: | Revision:

ffmpeg / libavformat / nut.c @ 99b17f25

History | View | Annotate | Download (13.8 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 99b17f25 Alex Beregszaszi
        put_v(bc, i /*s->streams[i]->index*/);
240 3aa180b8 Alex Beregszaszi
        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 99b17f25 Alex Beregszaszi
    put_b(bc, LIBAVFORMAT_IDENT "\0", strlen(LIBAVFORMAT_IDENT));
314
    
315
    put_v(bc, 0); /* eof info */
316 3aa180b8 Alex Beregszaszi

317 3ac8749b Michael Niedermayer
    put_be32(bc, 0); /* FIXME: checksum */
318 203504d9 Michael Niedermayer
    update_packetheader(nut, bc, 0);
319 3aa180b8 Alex Beregszaszi
#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 3ac8749b Michael Niedermayer
    int flags, size2;
333 3aa180b8 Alex Beregszaszi
    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 203504d9 Michael Niedermayer
    put_packetheader(nut, bc, size+(key_frame?8:0)+20);
343 3aa180b8 Alex Beregszaszi
344
    if (key_frame)
345 3ac8749b Michael Niedermayer
        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 3aa180b8 Alex Beregszaszi
    put_v(bc, stream_index);
356 99b17f25 Alex Beregszaszi
    put_s(bc, force_pts); /* lsb_timestamp */
357 203504d9 Michael Niedermayer
    update_packetheader(nut, bc, size);
358 3aa180b8 Alex Beregszaszi
    
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 203504d9 Michael Niedermayer
        put_packetheader(nut, bc, 64);
378 3ac8749b Michael Niedermayer
        put_be64(bc, INDEX_STARTCODE);
379 3aa180b8 Alex Beregszaszi
        put_v(bc, s->streams[i]->id);
380
        put_v(bc, ...);
381 3ac8749b Michael Niedermayer
        put_be32(bc, 0); /* FIXME: checksum */
382 203504d9 Michael Niedermayer
        update_packetheader(nut, bc, 0);
383 3aa180b8 Alex Beregszaszi
    }
384
#endif
385
386
    put_flush_packet(bc);
387
388
    return 0;
389
}
390
391
static int nut_probe(AVProbeData *p)
392
{
393 3ac8749b Michael Niedermayer
    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 3aa180b8 Alex Beregszaszi
}
406
407
static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
408
{
409
    NUTContext *nut = s->priv_data;
410
    ByteIOContext *bc = &s->pb;
411 3ac8749b Michael Niedermayer
    uint64_t tmp;
412 3aa180b8 Alex Beregszaszi
    int cur_stream, nb_streams;
413
    
414
    /* main header */
415
    get_packetheader(nut, bc);
416 3ac8749b Michael Niedermayer
    tmp = get_be64(bc);
417
    if (tmp != MAIN_STARTCODE)
418
        fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
419 3aa180b8 Alex Beregszaszi
    
420
    tmp = get_v(bc);
421
    if (tmp != 0)
422 3ac8749b Michael Niedermayer
        fprintf(stderr, "bad version (%Ld)\n", tmp);
423 3aa180b8 Alex Beregszaszi
    
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 3ac8749b Michael Niedermayer
    get_be32(bc); /* checkusm */
430 3aa180b8 Alex Beregszaszi
    
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 3ac8749b Michael Niedermayer
        tmp = get_be64(bc);
441
        if (tmp != STREAM_STARTCODE)
442
            fprintf(stderr, "damaged? startcode!=1 (%Ld)\n", tmp);
443 3aa180b8 Alex Beregszaszi
        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 3ac8749b Michael Niedermayer
//                tmp = get_be32(bc);
453
                get_b(bc, (char*)&tmp, 4);
454 3aa180b8 Alex Beregszaszi
                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 3ac8749b Michael Niedermayer
//                tmp = get_be32(bc);
462
                get_b(bc, (char*)&tmp, 4);
463 3aa180b8 Alex Beregszaszi
                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 3ac8749b Michael Niedermayer
    int id, timestamp, size;
508 3aa180b8 Alex Beregszaszi
    int key_frame = 0;
509 3ac8749b Michael Niedermayer
    uint64_t tmp;
510 3aa180b8 Alex Beregszaszi
511
    get_packetheader(nut, bc);
512
513
    if (url_feof(bc))
514
        return -1;
515
    
516
    tmp = get_byte(bc);
517 3ac8749b Michael Niedermayer
    if (tmp & 0x80) /* zero bit set? */
518 3aa180b8 Alex Beregszaszi
    {
519 3ac8749b Michael Niedermayer
        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 3aa180b8 Alex Beregszaszi
        {
524
            key_frame = 1;
525
            tmp = get_byte(bc); /* flags */
526
        }
527
        else
528 3ac8749b Michael Niedermayer
            fprintf(stderr, "error in zero bit / startcode %LX\n", tmp);
529 3aa180b8 Alex Beregszaszi
    }
530 3ac8749b Michael Niedermayer
#if 0
531
    if (((tmp & 0x60)>>5) > 3) /* priority <= 3 */
532 3aa180b8 Alex Beregszaszi
        fprintf(stderr, "sanity check failed!\n");
533 3ac8749b Michael Niedermayer
#endif
534 3aa180b8 Alex Beregszaszi
    id = get_v(bc);
535
    timestamp = get_s(bc);
536
    
537
    size = (nut->curr_frame_size - (url_ftell(bc)-nut->curr_frame_start));
538 3ac8749b Michael Niedermayer
    dprintf("flags: 0x%Lx, timestamp: %d, packet size: %d\n", tmp, timestamp, size);
539 3aa180b8 Alex Beregszaszi
    
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 99b17f25 Alex Beregszaszi
    CODEC_ID_AC3,
577 3aa180b8 Alex Beregszaszi
#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
}