b5f4697de99613d170fdfb2c211c6f9eec4298f6
[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(&h263_format);
136     register_avformat(&rm_format);
137     register_avformat(&asf_format);
138     register_avformat(&avi_format);
139     register_avformat(&mpjpeg_format);
140     register_avformat(&jpeg_format);
141     register_avformat(&swf_format);
142     register_avformat(&wav_format);
143     register_avformat(&pcm_format);
144     register_avformat(&rawvideo_format);
145 #ifndef CONFIG_WIN32
146     register_avformat(&ffm_format);
147 #endif
148     register_avformat(&pgm_format);
149     register_avformat(&ppm_format);
150     register_avformat(&pgmyuv_format);
151     register_avformat(&imgyuv_format);
152     register_avformat(&pgmpipe_format);
153     register_avformat(&pgmyuvpipe_format);
154     register_avformat(&ppmpipe_format);
155
156     register_protocol(&file_protocol);
157     register_protocol(&pipe_protocol);
158 #ifdef CONFIG_GRAB
159     register_protocol(&audio_protocol);
160     register_protocol(&video_protocol);
161 #endif
162 #ifndef CONFIG_WIN32
163     register_protocol(&udp_protocol);
164     register_protocol(&http_protocol);
165 #endif
166 }
167
168 /* memory handling */
169
170 int av_new_packet(AVPacket *pkt, int size)
171 {
172     pkt->data = malloc(size);
173     if (!pkt->data)
174         return -ENOMEM;
175     pkt->size = size;
176     /* sane state */
177     pkt->pts = 0;
178     pkt->stream_index = 0;
179     pkt->flags = 0;
180     return 0;
181 }
182
183 void av_free_packet(AVPacket *pkt)
184 {
185     free(pkt->data);
186     /* fail safe */
187     pkt->data = NULL;
188     pkt->size = 0;
189 }
190
191 /* fifo handling */
192
193 int fifo_init(FifoBuffer *f, int size)
194 {
195     f->buffer = malloc(size);
196     if (!f->buffer)
197         return -1;
198     f->end = f->buffer + size;
199     f->wptr = f->rptr = f->buffer;
200     return 0;
201 }
202
203 void fifo_free(FifoBuffer *f)
204 {
205     free(f->buffer);
206 }
207
208 int fifo_size(FifoBuffer *f, UINT8 *rptr)
209 {
210     int size;
211
212     if (f->wptr >= rptr) {
213         size = f->wptr - rptr;
214     } else {
215         size = (f->end - rptr) + (f->wptr - f->buffer);
216     }
217     return size;
218 }
219
220 /* get data from the fifo (return -1 if not enough data) */
221 int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr)
222 {
223     UINT8 *rptr = *rptr_ptr;
224     int size, len;
225
226     if (f->wptr >= rptr) {
227         size = f->wptr - rptr;
228     } else {
229         size = (f->end - rptr) + (f->wptr - f->buffer);
230     }
231     
232     if (size < buf_size)
233         return -1;
234     while (buf_size > 0) {
235         len = f->end - rptr;
236         if (len > buf_size)
237             len = buf_size;
238         memcpy(buf, rptr, len);
239         buf += len;
240         rptr += len;
241         if (rptr >= f->end)
242             rptr = f->buffer;
243         buf_size -= len;
244     }
245     *rptr_ptr = rptr;
246     return 0;
247 }
248
249 void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr)
250 {
251     int len;
252     UINT8 *wptr;
253     wptr = *wptr_ptr;
254     while (size > 0) {
255         len = f->end - wptr;
256         if (len > size)
257             len = size;
258         memcpy(wptr, buf, len);
259         wptr += len;
260         if (wptr >= f->end)
261             wptr = f->buffer;
262         buf += len;
263         size -= len;
264     }
265     *wptr_ptr = wptr;
266 }
267
268 /* media file handling */
269
270 AVFormatContext *av_open_input_file(const char *filename, int buf_size)
271 {
272     AVFormatParameters params, *ap;
273     AVFormat *fmt;
274     AVFormatContext *ic = NULL;
275     URLFormat url_format;
276     int err;
277
278     ic = av_mallocz(sizeof(AVFormatContext));
279     if (!ic)
280         goto fail;
281     if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0)
282         goto fail;
283     
284     if (buf_size > 0) {
285         url_setbufsize(&ic->pb, buf_size);
286     }
287
288     /* find format */
289     err = url_getformat(url_fileno(&ic->pb), &url_format);
290     if (err >= 0) {
291         fmt = guess_format(url_format.format_name, NULL, NULL);
292         ap = &params;
293         ap->sample_rate = url_format.sample_rate;
294         ap->frame_rate = url_format.frame_rate;
295         ap->channels = url_format.channels;
296         ap->width = url_format.width;
297         ap->height = url_format.height;
298         ap->pix_fmt = url_format.pix_fmt;
299     } else {
300         fmt = guess_format(NULL, filename, NULL);
301         ap = NULL;
302     }
303     if (!fmt || !fmt->read_header) {
304         return NULL;
305     }
306     ic->format = fmt;
307
308     err = ic->format->read_header(ic, ap);
309     if (err < 0) {
310         url_fclose(&ic->pb);
311         goto fail;
312     }
313     
314     return ic;
315
316  fail:
317     if (ic)
318         free(ic);
319     return NULL;
320 }
321
322 int av_read_packet(AVFormatContext *s, AVPacket *pkt)
323 {
324     AVPacketList *pktl;
325
326     pktl = s->packet_buffer;
327     if (pktl) {
328         /* read packet from packet buffer, if there is data */
329         *pkt = pktl->pkt;
330         s->packet_buffer = pktl->next;
331         free(pktl);
332         return 0;
333     } else {
334         return s->format->read_packet(s, pkt);
335     }
336 }
337
338 void av_close_input_file(AVFormatContext *s)
339 {
340     int i;
341
342     if (s->format->read_close)
343         s->format->read_close(s);
344     for(i=0;i<s->nb_streams;i++) {
345         free(s->streams[i]);
346     }
347     if (s->packet_buffer) {
348         AVPacketList *p, *p1;
349         p = s->packet_buffer;
350         while (p != NULL) {
351             p1 = p->next;
352             av_free_packet(&p->pkt);
353             free(p);
354             p = p1;
355         }
356         s->packet_buffer = NULL;
357     }
358     url_fclose(&s->pb);
359     free(s);
360 }
361
362
363 int av_write_packet(AVFormatContext *s, AVPacket *pkt)
364 {
365     /* XXX: currently, an emulation because internal API must change */
366     return s->format->write_packet(s, pkt->stream_index, pkt->data, pkt->size);
367 }
368
369 /* "user interface" functions */
370
371 void dump_format(AVFormatContext *ic,
372                  int index, 
373                  const char *url,
374                  int is_output)
375 {
376     int i;
377     char buf[256];
378
379     fprintf(stderr, "%s #%d, %s, %s '%s':\n", 
380             is_output ? "Output" : "Input",
381             index, ic->format->name, 
382             is_output ? "to" : "from", url);
383     for(i=0;i<ic->nb_streams;i++) {
384         AVStream *st = ic->streams[i];
385         avcodec_string(buf, sizeof(buf), &st->codec, is_output);
386         fprintf(stderr, "  Stream #%d.%d: %s\n", index, i, buf);
387     }
388 }
389
390 typedef struct {
391     const char *str;
392     int width, height;
393 } SizeEntry;
394
395 static SizeEntry sizes[] = {
396     { "sqcif", 128, 96 },
397     { "qcif", 176, 144 },
398     { "cif", 352, 288 },
399     { "4cif", 704, 576 },
400 };
401     
402 int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
403 {
404     int i;
405     int n = sizeof(sizes) / sizeof(SizeEntry);
406     const char *p;
407     int frame_width = 0, frame_height = 0;
408
409     for(i=0;i<n;i++) {
410         if (!strcmp(sizes[i].str, str)) {
411             frame_width = sizes[i].width;
412             frame_height = sizes[i].height;
413             break;
414         }
415     }
416     if (i == n) {
417         p = str;
418         frame_width = strtol(p, (char **)&p, 10);
419         if (*p)
420             p++;
421         frame_height = strtol(p, (char **)&p, 10);
422     }
423     if (frame_width <= 0 || frame_height <= 0)
424         return -1;
425     *width_ptr = frame_width;
426     *height_ptr = frame_height;
427     return 0;
428 }
429
430 INT64 gettime(void)
431 {
432 #ifdef CONFIG_WIN32
433     struct _timeb tb;
434     _ftime(&tb);
435     return ((INT64)tb.time * INT64_C(1000) + (INT64)tb.millitm) * INT64_C(1000);
436 #else
437     struct timeval tv;
438     gettimeofday(&tv,NULL);
439     return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
440 #endif
441 }
442
443 /* syntax: [YYYY-MM-DD ][[HH:]MM:]SS[.m...] . Return the date in micro seconds since 1970 */
444 INT64 parse_date(const char *datestr, int duration)
445 {
446     const char *p;
447     INT64 t;
448     int sec;
449
450     p = datestr;
451     if (!duration) {
452         static const UINT8 months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
453         int year, month, day, i;
454
455         if (strlen(p) >= 5 && p[4] == '-') {
456             
457             year = strtol(p, (char **)&p, 10);
458             if (*p)
459                 p++;
460             month = strtol(p, (char **)&p, 10) - 1;
461             if (*p)
462                 p++;
463             day = strtol(p, (char **)&p, 10) - 1;
464             if (*p)
465                 p++;
466             day += (year - 1970) * 365;
467             /* if >= March, take February of current year into account too */
468             if (month >= 2)
469                 year++;
470             for(i=1970;i<year;i++) {
471                 if ((i % 100) == 0) {
472                     if ((i % 400) == 0) day++;
473                 } else if ((i % 4) == 0) {
474                     day++;
475                 }
476             }
477             for(i=0;i<month;i++)
478                 day += months[i];
479         } else {
480             day = (time(NULL) / (3600 * 24));
481         }
482         t = day * (3600 * 24);
483     } else {
484         t = 0;
485     }
486     
487     sec = 0;
488     for(;;) {
489         int val;
490         val = strtol(p, (char **)&p, 10);
491         sec = sec * 60 + val;
492         if (*p != ':')
493             break;
494         p++;
495     }
496     t = (t + sec) * 1000000;
497     if (*p == '.') {
498         int val, n;
499         p++;
500         n = strlen(p);
501         if (n > 6)
502             n = 6;
503         val = strtol(p, NULL, 10);
504         while (n < 6) {
505             val = val * 10;
506             n++;
507         }
508         t += val;
509     }
510     return t;
511 }
512
513 /* syntax: '?tag1=val1&tag2=val2...'. No URL decoding is done. Return
514    1 if found */
515 int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
516 {
517     const char *p;
518     char tag[128], *q;
519
520     p = info;
521     if (*p == '?')
522         p++;
523     for(;;) {
524         q = tag;
525         while (*p != '\0' && *p != '=' && *p != '&') {
526             if ((q - tag) < sizeof(tag) - 1)
527                 *q++ = *p;
528             p++;
529         }
530         *q = '\0';
531         q = arg;
532         if (*p == '=') {
533             p++;
534             while (*p != '&' && *p != '\0') {
535                 if ((q - arg) < arg_size - 1)
536                     *q++ = *p;
537                 p++;
538             }
539             *q = '\0';
540         }
541         if (!strcmp(tag, tag1)) 
542             return 1;
543         if (*p != '&')
544             break;
545     }
546     return 0;
547 }
548