8520656a1b5bed167cc4afec29e9849eea84991d
[libav.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 #include "tick.h"
21 #ifndef CONFIG_WIN32
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <sys/time.h>
25 #include <time.h>
26 #else
27 #define strcasecmp _stricmp
28 #include <sys/types.h>
29 #include <sys/timeb.h>
30 #endif
31
32 AVFormat *first_format;
33
34 void register_avformat(AVFormat *format)
35 {
36 AVFormat **p;
37 p = &first_format;
38 while (*p != NULL) p = &(*p)->next;
39 *p = format;
40 format->next = NULL;
41 }
42
43 int match_ext(const char *filename, const char *extensions)
44 {
45 const char *ext, *p;
46 char ext1[32], *q;
47
48 ext = strrchr(filename, '.');
49 if (ext) {
50 ext++;
51 p = extensions;
52 for(;;) {
53 q = ext1;
54 while (*p != '\0' && *p != ',')
55 *q++ = *p++;
56 *q = '\0';
57 if (!strcasecmp(ext1, ext))
58 return 1;
59 if (*p == '\0')
60 break;
61 p++;
62 }
63 }
64 return 0;
65 }
66
67 AVFormat *guess_format(const char *short_name, const char *filename, const char *mime_type)
68 {
69 AVFormat *fmt, *fmt_found;
70 int score_max, score;
71
72 /* find the proper file type */
73 fmt_found = NULL;
74 score_max = 0;
75 fmt = first_format;
76 while (fmt != NULL) {
77 score = 0;
78 if (fmt->name && short_name && !strcmp(fmt->name, short_name))
79 score += 100;
80 if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
81 score += 10;
82 if (filename && fmt->extensions &&
83 match_ext(filename, fmt->extensions)) {
84 score += 5;
85 }
86 if (score > score_max) {
87 score_max = score;
88 fmt_found = fmt;
89 }
90 fmt = fmt->next;
91 }
92 return fmt_found;
93 }
94
95 /* return TRUE if val is a prefix of str. If it returns TRUE, ptr is
96 set to the next character in 'str' after the prefix */
97 int strstart(const char *str, const char *val, const char **ptr)
98 {
99 const char *p, *q;
100 p = str;
101 q = val;
102 while (*q != '\0') {
103 if (*p != *q)
104 return 0;
105 p++;
106 q++;
107 }
108 if (ptr)
109 *ptr = p;
110 return 1;
111 }
112
113 void nstrcpy(char *buf, int buf_size, const char *str)
114 {
115 int c;
116 char *q = buf;
117
118 for(;;) {
119 c = *str++;
120 if (c == 0 || q >= buf + buf_size - 1)
121 break;
122 *q++ = c;
123 }
124 *q = '\0';
125 }
126
127 void register_all(void)
128 {
129 avcodec_init();
130 avcodec_register_all();
131
132 register_avformat(&mp2_format);
133 register_avformat(&ac3_format);
134 register_avformat(&mpeg_mux_format);
135 register_avformat(&mpeg1video_format);
136 register_avformat(&mjpeg_format);
137 register_avformat(&h263_format);
138 register_avformat(&rm_format);
139 register_avformat(&asf_format);
140 register_avformat(&avi_format);
141 register_avformat(&mov_format);
142 register_avformat(&mp4_format);
143 register_avformat(&mpjpeg_format);
144 register_avformat(&jpeg_format);
145 register_avformat(&single_jpeg_format);
146 register_avformat(&swf_format);
147 register_avformat(&gif_format);
148 register_avformat(&au_format);
149 register_avformat(&wav_format);
150 register_avformat(&pcm_s16le_format);
151 register_avformat(&pcm_s16be_format);
152 register_avformat(&pcm_u16le_format);
153 register_avformat(&pcm_u16be_format);
154 register_avformat(&pcm_s8_format);
155 register_avformat(&pcm_u8_format);
156 register_avformat(&pcm_mulaw_format);
157 register_avformat(&pcm_alaw_format);
158 register_avformat(&rawvideo_format);
159 #ifndef CONFIG_WIN32
160 register_avformat(&ffm_format);
161 #endif
162 register_avformat(&pgm_format);
163 register_avformat(&ppm_format);
164 register_avformat(&pgmyuv_format);
165 register_avformat(&imgyuv_format);
166 register_avformat(&pgmpipe_format);
167 register_avformat(&pgmyuvpipe_format);
168 register_avformat(&ppmpipe_format);
169 #ifdef CONFIG_GRAB
170 register_avformat(&video_grab_device_format);
171 register_avformat(&audio_device_format);
172 #endif
173
174 /* file protocols */
175 register_protocol(&file_protocol);
176 register_protocol(&pipe_protocol);
177 #ifndef CONFIG_WIN32
178 register_protocol(&udp_protocol);
179 register_protocol(&http_protocol);
180 #endif
181 }
182
183 /* memory handling */
184
185 int av_new_packet(AVPacket *pkt, int size)
186 {
187 pkt->data = malloc(size);
188 if (!pkt->data)
189 return -ENOMEM;
190 pkt->size = size;
191 /* sane state */
192 pkt->pts = 0;
193 pkt->stream_index = 0;
194 pkt->flags = 0;
195 return 0;
196 }
197
198 void av_free_packet(AVPacket *pkt)
199 {
200 free(pkt->data);
201 /* fail safe */
202 pkt->data = NULL;
203 pkt->size = 0;
204 }
205
206 /* fifo handling */
207
208 int fifo_init(FifoBuffer *f, int size)
209 {
210 f->buffer = malloc(size);
211 if (!f->buffer)
212 return -1;
213 f->end = f->buffer + size;
214 f->wptr = f->rptr = f->buffer;
215 return 0;
216 }
217
218 void fifo_free(FifoBuffer *f)
219 {
220 free(f->buffer);
221 }
222
223 int fifo_size(FifoBuffer *f, UINT8 *rptr)
224 {
225 int size;
226
227 if (f->wptr >= rptr) {
228 size = f->wptr - rptr;
229 } else {
230 size = (f->end - rptr) + (f->wptr - f->buffer);
231 }
232 return size;
233 }
234
235 /* get data from the fifo (return -1 if not enough data) */
236 int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr)
237 {
238 UINT8 *rptr = *rptr_ptr;
239 int size, len;
240
241 if (f->wptr >= rptr) {
242 size = f->wptr - rptr;
243 } else {
244 size = (f->end - rptr) + (f->wptr - f->buffer);
245 }
246
247 if (size < buf_size)
248 return -1;
249 while (buf_size > 0) {
250 len = f->end - rptr;
251 if (len > buf_size)
252 len = buf_size;
253 memcpy(buf, rptr, len);
254 buf += len;
255 rptr += len;
256 if (rptr >= f->end)
257 rptr = f->buffer;
258 buf_size -= len;
259 }
260 *rptr_ptr = rptr;
261 return 0;
262 }
263
264 void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr)
265 {
266 int len;
267 UINT8 *wptr;
268 wptr = *wptr_ptr;
269 while (size > 0) {
270 len = f->end - wptr;
271 if (len > size)
272 len = size;
273 memcpy(wptr, buf, len);
274 wptr += len;
275 if (wptr >= f->end)
276 wptr = f->buffer;
277 buf += len;
278 size -= len;
279 }
280 *wptr_ptr = wptr;
281 }
282
283 /* media file handling.
284 'filename' is the filename to open.
285 'format_name' is used to force the file format (NULL if auto guess).
286 'buf_size' is the optional buffer size (zero if default is OK).
287 'ap' are additionnal parameters needed when opening the file (NULL if default).
288 */
289
290 AVFormatContext *av_open_input_file(const char *filename,
291 const char *format_name,
292 int buf_size,
293 AVFormatParameters *ap)
294 {
295 AVFormat *fmt;
296 AVFormatContext *ic = NULL;
297 int err;
298
299 ic = av_mallocz(sizeof(AVFormatContext));
300 if (!ic)
301 goto fail;
302
303 /* find format */
304 if (format_name != NULL) {
305 fmt = guess_format(format_name, NULL, NULL);
306 } else {
307 fmt = guess_format(NULL, filename, NULL);
308 }
309 if (!fmt || !fmt->read_header) {
310 return NULL;
311 }
312 ic->format = fmt;
313
314 /* if no file needed do not try to open one */
315 if (!(fmt->flags & AVFMT_NOFILE)) {
316 if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0)
317 goto fail;
318 if (buf_size > 0) {
319 url_setbufsize(&ic->pb, buf_size);
320 }
321 }
322
323 err = ic->format->read_header(ic, ap);
324 if (err < 0) {
325 if (!(fmt->flags & AVFMT_NOFILE)) {
326 url_fclose(&ic->pb);
327 }
328 goto fail;
329 }
330
331 return ic;
332
333 fail:
334 if (ic)
335 free(ic);
336 return NULL;
337 }
338
339 int av_read_packet(AVFormatContext *s, AVPacket *pkt)
340 {
341 AVPacketList *pktl;
342
343 pktl = s->packet_buffer;
344 if (pktl) {
345 /* read packet from packet buffer, if there is data */
346 *pkt = pktl->pkt;
347 s->packet_buffer = pktl->next;
348 free(pktl);
349 return 0;
350 } else {
351 return s->format->read_packet(s, pkt);
352 }
353 }
354
355 void av_close_input_file(AVFormatContext *s)
356 {
357 int i;
358
359 if (s->format->read_close)
360 s->format->read_close(s);
361 for(i=0;i<s->nb_streams;i++) {
362 free(s->streams[i]);
363 }
364 if (s->packet_buffer) {
365 AVPacketList *p, *p1;
366 p = s->packet_buffer;
367 while (p != NULL) {
368 p1 = p->next;
369 av_free_packet(&p->pkt);
370 free(p);
371 p = p1;
372 }
373 s->packet_buffer = NULL;
374 }
375 if (!(s->format->flags & AVFMT_NOFILE)) {
376 url_fclose(&s->pb);
377 }
378 free(s);
379 }
380
381
382 int av_write_packet(AVFormatContext *s, AVPacket *pkt, int force_pts)
383 {
384 /* XXX: currently, an emulation because internal API must change */
385 return s->format->write_packet(s, pkt->stream_index, pkt->data, pkt->size, force_pts);
386 }
387
388 /* "user interface" functions */
389
390 void dump_format(AVFormatContext *ic,
391 int index,
392 const char *url,
393 int is_output)
394 {
395 int i;
396 char buf[256];
397
398 fprintf(stderr, "%s #%d, %s, %s '%s':\n",
399 is_output ? "Output" : "Input",
400 index, ic->format->name,
401 is_output ? "to" : "from", url);
402 for(i=0;i<ic->nb_streams;i++) {
403 AVStream *st = ic->streams[i];
404 avcodec_string(buf, sizeof(buf), &st->codec, is_output);
405 fprintf(stderr, " Stream #%d.%d: %s\n", index, i, buf);
406 }
407 }
408
409 typedef struct {
410 const char *str;
411 int width, height;
412 } SizeEntry;
413
414 static SizeEntry sizes[] = {
415 { "sqcif", 128, 96 },
416 { "qcif", 176, 144 },
417 { "cif", 352, 288 },
418 { "4cif", 704, 576 },
419 };
420
421 int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
422 {
423 int i;
424 int n = sizeof(sizes) / sizeof(SizeEntry);
425 const char *p;
426 int frame_width = 0, frame_height = 0;
427
428 for(i=0;i<n;i++) {
429 if (!strcmp(sizes[i].str, str)) {
430 frame_width = sizes[i].width;
431 frame_height = sizes[i].height;
432 break;
433 }
434 }
435 if (i == n) {
436 p = str;
437 frame_width = strtol(p, (char **)&p, 10);
438 if (*p)
439 p++;
440 frame_height = strtol(p, (char **)&p, 10);
441 }
442 if (frame_width <= 0 || frame_height <= 0)
443 return -1;
444 *width_ptr = frame_width;
445 *height_ptr = frame_height;
446 return 0;
447 }
448
449 INT64 gettime(void)
450 {
451 #ifdef CONFIG_WIN32
452 struct _timeb tb;
453 _ftime(&tb);
454 return ((INT64)tb.time * INT64_C(1000) + (INT64)tb.millitm) * INT64_C(1000);
455 #else
456 struct timeval tv;
457 gettimeofday(&tv,NULL);
458 return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
459 #endif
460 }
461
462 /* syntax: [YYYY-MM-DD ][[HH:]MM:]SS[.m...] . Return the date in micro seconds since 1970 */
463 INT64 parse_date(const char *datestr, int duration)
464 {
465 const char *p;
466 INT64 t;
467 int sec;
468
469 p = datestr;
470 if (!duration) {
471 static const UINT8 months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
472 int year, month, day, i;
473
474 if (strlen(p) >= 5 && p[4] == '-') {
475
476 year = strtol(p, (char **)&p, 10);
477 if (*p)
478 p++;
479 month = strtol(p, (char **)&p, 10) - 1;
480 if (*p)
481 p++;
482 day = strtol(p, (char **)&p, 10) - 1;
483 if (*p)
484 p++;
485 day += (year - 1970) * 365;
486 /* if >= March, take February of current year into account too */
487 if (month >= 2)
488 year++;
489 for(i=1970;i<year;i++) {
490 if ((i % 100) == 0) {
491 if ((i % 400) == 0) day++;
492 } else if ((i % 4) == 0) {
493 day++;
494 }
495 }
496 for(i=0;i<month;i++)
497 day += months[i];
498 } else {
499 day = (time(NULL) / (3600 * 24));
500 }
501 t = day * (3600 * 24);
502 } else {
503 t = 0;
504 }
505
506 sec = 0;
507 for(;;) {
508 int val;
509 val = strtol(p, (char **)&p, 10);
510 sec = sec * 60 + val;
511 if (*p != ':')
512 break;
513 p++;
514 }
515 t = (t + sec) * 1000000;
516 if (*p == '.') {
517 int val, n;
518 p++;
519 n = strlen(p);
520 if (n > 6)
521 n = 6;
522 val = strtol(p, NULL, 10);
523 while (n < 6) {
524 val = val * 10;
525 n++;
526 }
527 t += val;
528 }
529 return t;
530 }
531
532 /* syntax: '?tag1=val1&tag2=val2...'. No URL decoding is done. Return
533 1 if found */
534 int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
535 {
536 const char *p;
537 char tag[128], *q;
538
539 p = info;
540 if (*p == '?')
541 p++;
542 for(;;) {
543 q = tag;
544 while (*p != '\0' && *p != '=' && *p != '&') {
545 if ((q - tag) < sizeof(tag) - 1)
546 *q++ = *p;
547 p++;
548 }
549 *q = '\0';
550 q = arg;
551 if (*p == '=') {
552 p++;
553 while (*p != '&' && *p != '\0') {
554 if ((q - arg) < arg_size - 1)
555 *q++ = *p;
556 p++;
557 }
558 *q = '\0';
559 }
560 if (!strcmp(tag, tag1))
561 return 1;
562 if (*p != '&')
563 break;
564 }
565 return 0;
566 }
567
568 /* Return in 'buf' the path with '%d' replaced by number. Also handles
569 the '%0nd' format where 'n' is the total number of digits and
570 '%%'. Return 0 if OK, and -1 if format error */
571 int get_frame_filename(char *buf, int buf_size,
572 const char *path, int number)
573 {
574 const char *p;
575 char *q, buf1[20];
576 int nd, len, c, percentd_found;
577
578 q = buf;
579 p = path;
580 percentd_found = 0;
581 for(;;) {
582 c = *p++;
583 if (c == '\0')
584 break;
585 if (c == '%') {
586 nd = 0;
587 while (*p >= '0' && *p <= '9') {
588 nd = nd * 10 + *p++ - '0';
589 }
590 c = *p++;
591 switch(c) {
592 case '%':
593 goto addchar;
594 case 'd':
595 if (percentd_found)
596 goto fail;
597 percentd_found = 1;
598 snprintf(buf1, sizeof(buf1), "%0*d", nd, number);
599 len = strlen(buf1);
600 if ((q - buf + len) > buf_size - 1)
601 goto fail;
602 memcpy(q, buf1, len);
603 q += len;
604 break;
605 default:
606 goto fail;
607 }
608 } else {
609 addchar:
610 if ((q - buf) < buf_size - 1)
611 *q++ = c;
612 }
613 }
614 if (!percentd_found)
615 goto fail;
616 *q = '\0';
617 return 0;
618 fail:
619 *q = '\0';
620 return -1;
621 }
622
623 static int gcd(INT64 a, INT64 b)
624 {
625 INT64 c;
626
627 while (1) {
628 c = a % b;
629 if (c == 0)
630 return b;
631 a = b;
632 b = c;
633 }
634 }
635
636 void ticker_init(Ticker *tick, INT64 inrate, INT64 outrate)
637 {
638 int g;
639
640 g = gcd(inrate, outrate);
641 inrate /= g;
642 outrate /= g;
643
644 tick->value = -outrate/2;
645
646 tick->inrate = inrate;
647 tick->outrate = outrate;
648 tick->div = tick->outrate / tick->inrate;
649 tick->mod = tick->outrate % tick->inrate;
650 }