added raw mjpeg
[ffmpeg.git] / libav / utils.c
1 /*
2  * Various utilities for ffmpeg system
3  * Copyright (c) 2000,2001 Gerard Lantau
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program 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
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 #include "avformat.h"
20 #ifndef CONFIG_WIN32
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <sys/time.h>
24 #include <time.h>
25 #else
26 #define strcasecmp _stricmp
27 #include <sys/types.h>
28 #include <sys/timeb.h>
29 #endif
30
31 AVFormat *first_format;
32
33 void register_avformat(AVFormat *format)
34 {
35     AVFormat **p;
36     p = &first_format;
37     while (*p != NULL) p = &(*p)->next;
38     *p = format;
39     format->next = NULL;
40 }
41
42 int match_ext(const char *filename, const char *extensions)
43 {
44     const char *ext, *p;
45     char ext1[32], *q;
46
47     ext = strrchr(filename, '.');
48     if (ext) {
49         ext++;
50         p = extensions;
51         for(;;) {
52             q = ext1;
53             while (*p != '\0' && *p != ',') 
54                 *q++ = *p++;
55             *q = '\0';
56             if (!strcasecmp(ext1, ext)) 
57                 return 1;
58             if (*p == '\0') 
59                 break;
60             p++;
61         }
62     }
63     return 0;
64 }
65
66 AVFormat *guess_format(const char *short_name, const char *filename, const char *mime_type)
67 {
68     AVFormat *fmt, *fmt_found;
69     int score_max, score;
70
71     /* find the proper file type */
72     fmt_found = NULL;
73     score_max = 0;
74     fmt = first_format;
75     while (fmt != NULL) {
76         score = 0;
77         if (fmt->name && short_name && !strcmp(fmt->name, short_name))
78             score += 100;
79         if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
80             score += 10;
81         if (filename && fmt->extensions && 
82             match_ext(filename, fmt->extensions)) {
83             score += 5;
84         }
85         if (score > score_max) {
86             score_max = score;
87             fmt_found = fmt;
88         }
89         fmt = fmt->next;
90     }
91     return fmt_found;
92 }   
93
94 /* return TRUE if val is a prefix of str. If it returns TRUE, ptr is
95    set to the next character in 'str' after the prefix */
96 int strstart(const char *str, const char *val, const char **ptr)
97 {
98     const char *p, *q;
99     p = str;
100     q = val;
101     while (*q != '\0') {
102         if (*p != *q)
103             return 0;
104         p++;
105         q++;
106     }
107     if (ptr)
108         *ptr = p;
109     return 1;
110 }
111
112 void nstrcpy(char *buf, int buf_size, const char *str)
113 {
114     int c;
115     char *q = buf;
116
117     for(;;) {
118         c = *str++;
119         if (c == 0 || q >= buf + buf_size - 1)
120             break;
121         *q++ = c;
122     }
123     *q = '\0';
124 }
125
126 void register_all(void)
127 {
128     avcodec_init();
129     avcodec_register_all();
130
131     register_avformat(&mp2_format);
132     register_avformat(&ac3_format);
133     register_avformat(&mpeg_mux_format);
134     register_avformat(&mpeg1video_format);
135     register_avformat(&mjpeg_format);
136     register_avformat(&h263_format);
137     register_avformat(&rm_format);
138     register_avformat(&asf_format);
139     register_avformat(&avi_format);
140     register_avformat(&mpjpeg_format);
141     register_avformat(&jpeg_format);
142     register_avformat(&single_jpeg_format);
143     register_avformat(&swf_format);
144     register_avformat(&wav_format);
145     register_avformat(&pcm_format);
146     register_avformat(&rawvideo_format);
147 #ifndef CONFIG_WIN32
148     register_avformat(&ffm_format);
149 #endif
150     register_avformat(&pgm_format);
151     register_avformat(&ppm_format);
152     register_avformat(&pgmyuv_format);
153     register_avformat(&imgyuv_format);
154     register_avformat(&pgmpipe_format);
155     register_avformat(&pgmyuvpipe_format);
156     register_avformat(&ppmpipe_format);
157
158     register_protocol(&file_protocol);
159     register_protocol(&pipe_protocol);
160 #ifdef CONFIG_GRAB
161     register_protocol(&audio_protocol);
162     register_protocol(&video_protocol);
163 #endif
164 #ifndef CONFIG_WIN32
165     register_protocol(&udp_protocol);
166     register_protocol(&http_protocol);
167 #endif
168 }
169
170 /* memory handling */
171
172 int av_new_packet(AVPacket *pkt, int size)
173 {
174     pkt->data = malloc(size);
175     if (!pkt->data)
176         return -ENOMEM;
177     pkt->size = size;
178     /* sane state */
179     pkt->pts = 0;
180     pkt->stream_index = 0;
181     pkt->flags = 0;
182     return 0;
183 }
184
185 void av_free_packet(AVPacket *pkt)
186 {
187     free(pkt->data);
188     /* fail safe */
189     pkt->data = NULL;
190     pkt->size = 0;
191 }
192
193 /* fifo handling */
194
195 int fifo_init(FifoBuffer *f, int size)
196 {
197     f->buffer = malloc(size);
198     if (!f->buffer)
199         return -1;
200     f->end = f->buffer + size;
201     f->wptr = f->rptr = f->buffer;
202     return 0;
203 }
204
205 void fifo_free(FifoBuffer *f)
206 {
207     free(f->buffer);
208 }
209
210 int fifo_size(FifoBuffer *f, UINT8 *rptr)
211 {
212     int size;
213
214     if (f->wptr >= rptr) {
215         size = f->wptr - rptr;
216     } else {
217         size = (f->end - rptr) + (f->wptr - f->buffer);
218     }
219     return size;
220 }
221
222 /* get data from the fifo (return -1 if not enough data) */
223 int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr)
224 {
225     UINT8 *rptr = *rptr_ptr;
226     int size, len;
227
228     if (f->wptr >= rptr) {
229         size = f->wptr - rptr;
230     } else {
231         size = (f->end - rptr) + (f->wptr - f->buffer);
232     }
233     
234     if (size < buf_size)
235         return -1;
236     while (buf_size > 0) {
237         len = f->end - rptr;
238         if (len > buf_size)
239             len = buf_size;
240         memcpy(buf, rptr, len);
241         buf += len;
242         rptr += len;
243         if (rptr >= f->end)
244             rptr = f->buffer;
245         buf_size -= len;
246     }
247     *rptr_ptr = rptr;
248     return 0;
249 }
250
251 void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr)
252 {
253     int len;
254     UINT8 *wptr;
255     wptr = *wptr_ptr;
256     while (size > 0) {
257         len = f->end - wptr;
258         if (len > size)
259             len = size;
260         memcpy(wptr, buf, len);
261         wptr += len;
262         if (wptr >= f->end)
263             wptr = f->buffer;
264         buf += len;
265         size -= len;
266     }
267     *wptr_ptr = wptr;
268 }
269
270 /* media file handling */
271
272 AVFormatContext *av_open_input_file(const char *filename, int buf_size)
273 {
274     AVFormatParameters params, *ap;
275     AVFormat *fmt;
276     AVFormatContext *ic = NULL;
277     URLFormat url_format;
278     int err;
279
280     ic = av_mallocz(sizeof(AVFormatContext));
281     if (!ic)
282         goto fail;
283     if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0)
284         goto fail;
285     
286     if (buf_size > 0) {
287         url_setbufsize(&ic->pb, buf_size);
288     }
289
290     /* find format */
291     err = url_getformat(url_fileno(&ic->pb), &url_format);
292     if (err >= 0) {
293         fmt = guess_format(url_format.format_name, NULL, NULL);
294         ap = &params;
295         ap->sample_rate = url_format.sample_rate;
296         ap->frame_rate = url_format.frame_rate;
297         ap->channels = url_format.channels;
298         ap->width = url_format.width;
299         ap->height = url_format.height;
300         ap->pix_fmt = url_format.pix_fmt;
301     } else {
302         fmt = guess_format(NULL, filename, NULL);
303         ap = NULL;
304     }
305     if (!fmt || !fmt->read_header) {
306         return NULL;
307     }
308     ic->format = fmt;
309
310     err = ic->format->read_header(ic, ap);
311     if (err < 0) {
312         url_fclose(&ic->pb);
313         goto fail;
314     }
315     
316     return ic;
317
318  fail:
319     if (ic)
320         free(ic);
321     return NULL;
322 }
323
324 int av_read_packet(AVFormatContext *s, AVPacket *pkt)
325 {
326     AVPacketList *pktl;
327
328     pktl = s->packet_buffer;
329     if (pktl) {
330         /* read packet from packet buffer, if there is data */
331         *pkt = pktl->pkt;
332         s->packet_buffer = pktl->next;
333         free(pktl);
334         return 0;
335     } else {
336         return s->format->read_packet(s, pkt);
337     }
338 }
339
340 void av_close_input_file(AVFormatContext *s)
341 {
342     int i;
343
344     if (s->format->read_close)
345         s->format->read_close(s);
346     for(i=0;i<s->nb_streams;i++) {
347         free(s->streams[i]);
348     }
349     if (s->packet_buffer) {
350         AVPacketList *p, *p1;
351         p = s->packet_buffer;
352         while (p != NULL) {
353             p1 = p->next;
354             av_free_packet(&p->pkt);
355             free(p);
356             p = p1;
357         }
358         s->packet_buffer = NULL;
359     }
360     url_fclose(&s->pb);
361     free(s);
362 }
363
364
365 int av_write_packet(AVFormatContext *s, AVPacket *pkt)
366 {
367     /* XXX: currently, an emulation because internal API must change */
368     return s->format->write_packet(s, pkt->stream_index, pkt->data, pkt->size);
369 }
370
371 /* "user interface" functions */
372
373 void dump_format(AVFormatContext *ic,
374                  int index, 
375                  const char *url,
376                  int is_output)
377 {
378     int i;
379     char buf[256];
380
381     fprintf(stderr, "%s #%d, %s, %s '%s':\n", 
382             is_output ? "Output" : "Input",
383             index, ic->format->name, 
384             is_output ? "to" : "from", url);
385     for(i=0;i<ic->nb_streams;i++) {
386         AVStream *st = ic->streams[i];
387         avcodec_string(buf, sizeof(buf), &st->codec, is_output);
388         fprintf(stderr, "  Stream #%d.%d: %s\n", index, i, buf);
389     }
390 }
391
392 typedef struct {
393     const char *str;
394     int width, height;
395 } SizeEntry;
396
397 static SizeEntry sizes[] = {
398     { "sqcif", 128, 96 },
399     { "qcif", 176, 144 },
400     { "cif", 352, 288 },
401     { "4cif", 704, 576 },
402 };
403     
404 int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
405 {
406     int i;
407     int n = sizeof(sizes) / sizeof(SizeEntry);
408     const char *p;
409     int frame_width = 0, frame_height = 0;
410
411     for(i=0;i<n;i++) {
412         if (!strcmp(sizes[i].str, str)) {
413             frame_width = sizes[i].width;
414             frame_height = sizes[i].height;
415             break;
416         }
417     }
418     if (i == n) {
419         p = str;
420         frame_width = strtol(p, (char **)&p, 10);
421         if (*p)
422             p++;
423         frame_height = strtol(p, (char **)&p, 10);
424     }
425     if (frame_width <= 0 || frame_height <= 0)
426         return -1;
427     *width_ptr = frame_width;
428     *height_ptr = frame_height;
429     return 0;
430 }
431
432 INT64 gettime(void)
433 {
434 #ifdef CONFIG_WIN32
435     struct _timeb tb;
436     _ftime(&tb);
437     return ((INT64)tb.time * INT64_C(1000) + (INT64)tb.millitm) * INT64_C(1000);
438 #else
439     struct timeval tv;
440     gettimeofday(&tv,NULL);
441     return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
442 #endif
443 }
444
445 /* syntax: [YYYY-MM-DD ][[HH:]MM:]SS[.m...] . Return the date in micro seconds since 1970 */
446 INT64 parse_date(const char *datestr, int duration)
447 {
448     const char *p;
449     INT64 t;
450     int sec;
451
452     p = datestr;
453     if (!duration) {
454         static const UINT8 months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
455         int year, month, day, i;
456
457         if (strlen(p) >= 5 && p[4] == '-') {
458             
459             year = strtol(p, (char **)&p, 10);
460             if (*p)
461                 p++;
462             month = strtol(p, (char **)&p, 10) - 1;
463             if (*p)
464                 p++;
465             day = strtol(p, (char **)&p, 10) - 1;
466             if (*p)
467                 p++;
468             day += (year - 1970) * 365;
469             /* if >= March, take February of current year into account too */
470             if (month >= 2)
471                 year++;
472             for(i=1970;i<year;i++) {
473                 if ((i % 100) == 0) {
474                     if ((i % 400) == 0) day++;
475                 } else if ((i % 4) == 0) {
476                     day++;
477                 }
478             }
479             for(i=0;i<month;i++)
480                 day += months[i];
481         } else {
482             day = (time(NULL) / (3600 * 24));
483         }
484         t = day * (3600 * 24);
485     } else {
486         t = 0;
487     }
488     
489     sec = 0;
490     for(;;) {
491         int val;
492         val = strtol(p, (char **)&p, 10);
493         sec = sec * 60 + val;
494         if (*p != ':')
495             break;
496         p++;
497     }
498     t = (t + sec) * 1000000;
499     if (*p == '.') {
500         int val, n;
501         p++;
502         n = strlen(p);
503         if (n > 6)
504             n = 6;
505         val = strtol(p, NULL, 10);
506         while (n < 6) {
507             val = val * 10;
508             n++;
509         }
510         t += val;
511     }
512     return t;
513 }
514
515 /* syntax: '?tag1=val1&tag2=val2...'. No URL decoding is done. Return
516    1 if found */
517 int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
518 {
519     const char *p;
520     char tag[128], *q;
521
522     p = info;
523     if (*p == '?')
524         p++;
525     for(;;) {
526         q = tag;
527         while (*p != '\0' && *p != '=' && *p != '&') {
528             if ((q - tag) < sizeof(tag) - 1)
529                 *q++ = *p;
530             p++;
531         }
532         *q = '\0';
533         q = arg;
534         if (*p == '=') {
535             p++;
536             while (*p != '&' && *p != '\0') {
537                 if ((q - arg) < arg_size - 1)
538                     *q++ = *p;
539                 p++;
540             }
541             *q = '\0';
542         }
543         if (!strcmp(tag, tag1)) 
544             return 1;
545         if (*p != '&')
546             break;
547     }
548     return 0;
549 }
550