]> git.sesse.net Git - ffmpeg/blob - libavformat/nut.c
92f478ee244d9935e8782c088e085d758d3ea21b
[ffmpeg] / libavformat / nut.c
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 }