split mux/demux related structures - added file probing support - improve media file...
[libav.git] / libav / utils.c
1 /*
2 * Various utilities for ffmpeg system
3 * Copyright (c) 2000, 2001, 2002 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 AVInputFormat *first_iformat;
33 AVOutputFormat *first_oformat;
34
35 void av_register_input_format(AVInputFormat *format)
36 {
37 AVInputFormat **p;
38 p = &first_iformat;
39 while (*p != NULL) p = &(*p)->next;
40 *p = format;
41 format->next = NULL;
42 }
43
44 void av_register_output_format(AVOutputFormat *format)
45 {
46 AVOutputFormat **p;
47 p = &first_oformat;
48 while (*p != NULL) p = &(*p)->next;
49 *p = format;
50 format->next = NULL;
51 }
52
53 int match_ext(const char *filename, const char *extensions)
54 {
55 const char *ext, *p;
56 char ext1[32], *q;
57
58 ext = strrchr(filename, '.');
59 if (ext) {
60 ext++;
61 p = extensions;
62 for(;;) {
63 q = ext1;
64 while (*p != '\0' && *p != ',')
65 *q++ = *p++;
66 *q = '\0';
67 if (!strcasecmp(ext1, ext))
68 return 1;
69 if (*p == '\0')
70 break;
71 p++;
72 }
73 }
74 return 0;
75 }
76
77 AVOutputFormat *guess_format(const char *short_name, const char *filename,
78 const char *mime_type)
79 {
80 AVOutputFormat *fmt, *fmt_found;
81 int score_max, score;
82
83 /* find the proper file type */
84 fmt_found = NULL;
85 score_max = 0;
86 fmt = first_oformat;
87 while (fmt != NULL) {
88 score = 0;
89 if (fmt->name && short_name && !strcmp(fmt->name, short_name))
90 score += 100;
91 if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
92 score += 10;
93 if (filename && fmt->extensions &&
94 match_ext(filename, fmt->extensions)) {
95 score += 5;
96 }
97 if (score > score_max) {
98 score_max = score;
99 fmt_found = fmt;
100 }
101 fmt = fmt->next;
102 }
103 return fmt_found;
104 }
105
106 AVInputFormat *av_find_input_format(const char *short_name)
107 {
108 AVInputFormat *fmt;
109 for(fmt = first_iformat; fmt != NULL; fmt = fmt->next) {
110 if (!strcmp(fmt->name, short_name))
111 return fmt;
112 }
113 return NULL;
114 }
115
116
117 /**
118 * Return TRUE if val is a prefix of str. If it returns TRUE, ptr is
119 * set to the next character in 'str' after the prefix.
120 *
121 * @param str input string
122 * @param val prefix to test
123 * @param ptr updated after the prefix in str in there is a match
124 * @return TRUE if there is a match
125 */
126 int strstart(const char *str, const char *val, const char **ptr)
127 {
128 const char *p, *q;
129 p = str;
130 q = val;
131 while (*q != '\0') {
132 if (*p != *q)
133 return 0;
134 p++;
135 q++;
136 }
137 if (ptr)
138 *ptr = p;
139 return 1;
140 }
141
142 /**
143 * Copy the string str to buf. If str length is bigger than buf_size -
144 * 1 then it is clamped to buf_size - 1.
145 * NOTE: this function does what strncpy should have done to be
146 * useful. NEVER use strncpy.
147 *
148 * @param buf destination buffer
149 * @param buf_size size of destination buffer
150 * @param str source string
151 */
152 void pstrcpy(char *buf, int buf_size, const char *str)
153 {
154 int c;
155 char *q = buf;
156
157 for(;;) {
158 c = *str++;
159 if (c == 0 || q >= buf + buf_size - 1)
160 break;
161 *q++ = c;
162 }
163 *q = '\0';
164 }
165
166 void register_all(void)
167 {
168 avcodec_init();
169 avcodec_register_all();
170
171 mpegps_init();
172 mpegts_init();
173 crc_init();
174 img_init();
175 raw_init();
176 rm_init();
177 asf_init();
178 avienc_init();
179 avidec_init();
180 wav_init();
181 swf_init();
182 au_init();
183 gif_init();
184 mov_init();
185 jpeg_init();
186
187 #ifndef CONFIG_WIN32
188 ffm_init();
189 #endif
190 #ifdef CONFIG_GRAB
191 video_grab_init();
192 audio_init();
193 #endif
194 /* file protocols */
195 register_protocol(&file_protocol);
196 register_protocol(&pipe_protocol);
197 #ifndef CONFIG_WIN32
198 register_protocol(&udp_protocol);
199 register_protocol(&http_protocol);
200 #endif
201 }
202
203 /* memory handling */
204
205 /**
206 * Allocate the payload of a packet and intialized its fields to default values.
207 *
208 * @param pkt packet
209 * @param size wanted payload size
210 * @return 0 if OK. AVERROR_xxx otherwise.
211 */
212 int av_new_packet(AVPacket *pkt, int size)
213 {
214 pkt->data = av_malloc(size);
215 if (!pkt->data)
216 return AVERROR_NOMEM;
217 pkt->size = size;
218 /* sane state */
219 pkt->pts = 0;
220 pkt->stream_index = 0;
221 pkt->flags = 0;
222 return 0;
223 }
224
225 /**
226 * Free a packet
227 *
228 * @param pkt packet to free
229 */
230 void av_free_packet(AVPacket *pkt)
231 {
232 av_freep(&pkt->data);
233 /* fail safe */
234 pkt->size = 0;
235 }
236
237 /* fifo handling */
238
239 int fifo_init(FifoBuffer *f, int size)
240 {
241 f->buffer = av_malloc(size);
242 if (!f->buffer)
243 return -1;
244 f->end = f->buffer + size;
245 f->wptr = f->rptr = f->buffer;
246 return 0;
247 }
248
249 void fifo_free(FifoBuffer *f)
250 {
251 av_free(f->buffer);
252 }
253
254 int fifo_size(FifoBuffer *f, UINT8 *rptr)
255 {
256 int size;
257
258 if (f->wptr >= rptr) {
259 size = f->wptr - rptr;
260 } else {
261 size = (f->end - rptr) + (f->wptr - f->buffer);
262 }
263 return size;
264 }
265
266 /* get data from the fifo (return -1 if not enough data) */
267 int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr)
268 {
269 UINT8 *rptr = *rptr_ptr;
270 int size, len;
271
272 if (f->wptr >= rptr) {
273 size = f->wptr - rptr;
274 } else {
275 size = (f->end - rptr) + (f->wptr - f->buffer);
276 }
277
278 if (size < buf_size)
279 return -1;
280 while (buf_size > 0) {
281 len = f->end - rptr;
282 if (len > buf_size)
283 len = buf_size;
284 memcpy(buf, rptr, len);
285 buf += len;
286 rptr += len;
287 if (rptr >= f->end)
288 rptr = f->buffer;
289 buf_size -= len;
290 }
291 *rptr_ptr = rptr;
292 return 0;
293 }
294
295 void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr)
296 {
297 int len;
298 UINT8 *wptr;
299 wptr = *wptr_ptr;
300 while (size > 0) {
301 len = f->end - wptr;
302 if (len > size)
303 len = size;
304 memcpy(wptr, buf, len);
305 wptr += len;
306 if (wptr >= f->end)
307 wptr = f->buffer;
308 buf += len;
309 size -= len;
310 }
311 *wptr_ptr = wptr;
312 }
313
314 int filename_number_test(const char *filename)
315 {
316 char buf[1024];
317 return get_frame_filename(buf, sizeof(buf), filename, 1);
318 }
319
320 /* guess file format */
321 static AVInputFormat *probe_input_format(AVProbeData *pd, int is_opened)
322 {
323 AVInputFormat *fmt1, *fmt;
324 int score, score_max;
325
326 fmt = NULL;
327 score_max = 0;
328 for(fmt1 = first_iformat; fmt1 != NULL; fmt1 = fmt1->next) {
329 if (!is_opened && !(fmt1->flags & AVFMT_NOFILE))
330 continue;
331 score = 0;
332 if (fmt1->extensions) {
333 if (match_ext(pd->filename, fmt1->extensions)) {
334 score = 50;
335 }
336 } else if (fmt1->read_probe) {
337 score = fmt1->read_probe(pd);
338 }
339 if (score > score_max) {
340 score_max = score;
341 fmt = fmt1;
342 }
343 }
344 return fmt;
345 }
346
347 /************************************************************/
348 /* input media file */
349
350 #define PROBE_BUF_SIZE 2048
351
352 /**
353 * Open a media file as input. The codec are not opened. Only the file
354 * header (if present) is read.
355 *
356 * @param ic_ptr the opened media file handle is put here
357 * @param filename filename to open.
358 * @param fmt if non NULL, force the file format to use
359 * @param buf_size optional buffer size (zero if default is OK)
360 * @param ap additionnal parameters needed when opening the file (NULL if default)
361 * @return 0 if OK. AVERROR_xxx otherwise.
362 */
363 int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
364 AVInputFormat *fmt,
365 int buf_size,
366 AVFormatParameters *ap)
367 {
368 AVFormatContext *ic = NULL;
369 int err;
370 char buf[PROBE_BUF_SIZE];
371 AVProbeData probe_data, *pd = &probe_data;
372
373 ic = av_mallocz(sizeof(AVFormatContext));
374 if (!ic) {
375 err = AVERROR_NOMEM;
376 goto fail;
377 }
378 pstrcpy(ic->filename, sizeof(ic->filename), filename);
379 pd->filename = ic->filename;
380 pd->buf = buf;
381 pd->buf_size = 0;
382
383 if (!fmt) {
384 /* guess format if no file can be opened */
385 fmt = probe_input_format(pd, 0);
386 }
387
388 /* if no file needed do not try to open one */
389 if (!fmt || !(fmt->flags & AVFMT_NOFILE)) {
390 if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0) {
391 err = AVERROR_IO;
392 goto fail;
393 }
394 if (buf_size > 0) {
395 url_setbufsize(&ic->pb, buf_size);
396 }
397 /* read probe data */
398 pd->buf_size = get_buffer(&ic->pb, buf, PROBE_BUF_SIZE);
399 url_fseek(&ic->pb, 0, SEEK_SET);
400 }
401
402 /* guess file format */
403 if (!fmt) {
404 fmt = probe_input_format(pd, 1);
405 }
406
407 /* if still no format found, error */
408 if (!fmt) {
409 err = AVERROR_NOFMT;
410 goto fail;
411 }
412
413 ic->iformat = fmt;
414
415 /* allocate private data */
416 ic->priv_data = av_mallocz(fmt->priv_data_size);
417 if (!ic->priv_data) {
418 err = AVERROR_NOMEM;
419 goto fail;
420 }
421
422 /* check filename in case of an image number is expected */
423 if (ic->iformat->flags & AVFMT_NEEDNUMBER) {
424 if (filename_number_test(ic->filename) < 0) {
425 err = AVERROR_NUMEXPECTED;
426 goto fail1;
427 }
428 }
429
430 err = ic->iformat->read_header(ic, ap);
431 if (err < 0)
432 goto fail1;
433 *ic_ptr = ic;
434 return 0;
435 fail1:
436 if (!(fmt->flags & AVFMT_NOFILE)) {
437 url_fclose(&ic->pb);
438 }
439 fail:
440 if (ic) {
441 av_free(ic->priv_data);
442 }
443 av_free(ic);
444 *ic_ptr = NULL;
445 return err;
446 }
447
448 /**
449 * Read a packet from a media file
450 * @param s media file handle
451 * @param pkt is filled
452 * @return 0 if OK. AVERROR_xxx if error.
453 */
454 int av_read_packet(AVFormatContext *s, AVPacket *pkt)
455 {
456 AVPacketList *pktl;
457
458 pktl = s->packet_buffer;
459 if (pktl) {
460 /* read packet from packet buffer, if there is data */
461 *pkt = pktl->pkt;
462 s->packet_buffer = pktl->next;
463 av_free(pktl);
464 return 0;
465 } else {
466 return s->iformat->read_packet(s, pkt);
467 }
468 }
469
470 /* state for codec information */
471 #define CSTATE_NOTFOUND 0
472 #define CSTATE_DECODING 1
473 #define CSTATE_FOUND 2
474
475 static int has_codec_parameters(AVCodecContext *enc)
476 {
477 int val;
478 switch(enc->codec_type) {
479 case CODEC_TYPE_AUDIO:
480 val = enc->sample_rate;
481 break;
482 case CODEC_TYPE_VIDEO:
483 val = enc->width;
484 break;
485 default:
486 val = 1;
487 break;
488 }
489 return (val != 0);
490 }
491
492 /**
493 * Read the beginning of a media file to get stream information. This
494 * is useful for file formats with no headers such as MPEG. This
495 * function also compute the real frame rate in case of mpeg2 repeat
496 * frame mode.
497 *
498 * @param ic media file handle
499 * @return >=0 if OK. AVERROR_xxx if error.
500 */
501 int av_find_stream_info(AVFormatContext *ic)
502 {
503 int i, count, ret, got_picture, size, read_size;
504 AVCodec *codec;
505 AVStream *st;
506 AVPacket *pkt;
507 AVPicture picture;
508 AVPacketList *pktl=NULL, **ppktl;
509 short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2];
510 UINT8 *ptr;
511 int min_read_size, max_read_size;
512
513 /* typical mpeg ts rate is 40 Mbits. DVD rate is about 10
514 Mbits. We read at most 0.1 second of file to find all streams */
515
516 /* XXX: base it on stream bitrate when possible */
517 if (ic->iformat == &mpegts_demux) {
518 /* maximum number of bytes we accept to read to find all the streams
519 in a file */
520 min_read_size = 3000000;
521 } else {
522 min_read_size = 125000;
523 }
524 /* max read size is 2 seconds of video max */
525 max_read_size = min_read_size * 20;
526
527 /* set initial codec state */
528 for(i=0;i<ic->nb_streams;i++) {
529 st = ic->streams[i];
530 if (has_codec_parameters(&st->codec))
531 st->codec_info_state = CSTATE_FOUND;
532 else
533 st->codec_info_state = CSTATE_NOTFOUND;
534 st->codec_info_nb_repeat_frames = 0;
535 st->codec_info_nb_real_frames = 0;
536 }
537
538 count = 0;
539 read_size = 0;
540 ppktl = &ic->packet_buffer;
541 for(;;) {
542 /* check if one codec still needs to be handled */
543 for(i=0;i<ic->nb_streams;i++) {
544 st = ic->streams[i];
545 if (st->codec_info_state != CSTATE_FOUND)
546 break;
547 }
548 if (i == ic->nb_streams) {
549 /* NOTE: if the format has no header, then we need to read
550 some packets to get most of the streams, so we cannot
551 stop here */
552 if (!(ic->iformat->flags & AVFMT_NOHEADER) ||
553 read_size >= min_read_size) {
554 /* if we found the info for all the codecs, we can stop */
555 ret = count;
556 break;
557 }
558 } else {
559 /* we did not get all the codec info, but we read too much data */
560 if (read_size >= max_read_size) {
561 ret = count;
562 break;
563 }
564 }
565
566 pktl = av_mallocz(sizeof(AVPacketList));
567 if (!pktl) {
568 ret = AVERROR_NOMEM;
569 break;
570 }
571
572 /* add the packet in the buffered packet list */
573 *ppktl = pktl;
574 ppktl = &pktl->next;
575
576 /* NOTE: a new stream can be added there if no header in file
577 (AVFMT_NOHEADER) */
578 pkt = &pktl->pkt;
579 if (ic->iformat->read_packet(ic, pkt) < 0) {
580 /* EOF or error */
581 ret = -1; /* we could not have all the codec parameters before EOF */
582 if ((ic->iformat->flags & AVFMT_NOHEADER) &&
583 i == ic->nb_streams)
584 ret = 0;
585 break;
586 }
587 read_size += pkt->size;
588
589 /* open new codecs */
590 for(i=0;i<ic->nb_streams;i++) {
591 st = ic->streams[i];
592 if (st->codec_info_state == CSTATE_NOTFOUND) {
593 /* set to found in case of error */
594 st->codec_info_state = CSTATE_FOUND;
595 codec = avcodec_find_decoder(st->codec.codec_id);
596 if (codec) {
597 ret = avcodec_open(&st->codec, codec);
598 if (ret >= 0)
599 st->codec_info_state = CSTATE_DECODING;
600 }
601 }
602 }
603
604 st = ic->streams[pkt->stream_index];
605 if (st->codec_info_state == CSTATE_DECODING) {
606 /* decode the data and update codec parameters */
607 ptr = pkt->data;
608 size = pkt->size;
609 while (size > 0) {
610 switch(st->codec.codec_type) {
611 case CODEC_TYPE_VIDEO:
612 ret = avcodec_decode_video(&st->codec, &picture,
613 &got_picture, ptr, size);
614 break;
615 case CODEC_TYPE_AUDIO:
616 ret = avcodec_decode_audio(&st->codec, samples,
617 &got_picture, ptr, size);
618 break;
619 default:
620 ret = -1;
621 break;
622 }
623 if (ret < 0) {
624 /* if error, simply ignore because another packet
625 may be OK */
626 break;
627 }
628 if (got_picture) {
629 /* we got the parameters - now we can stop
630 examining this stream */
631 /* XXX: add a codec info so that we can decide if
632 the codec can repeat frames */
633 if (st->codec.codec_id == CODEC_ID_MPEG1VIDEO &&
634 ic->iformat != &mpegts_demux &&
635 st->codec.sub_id == 2) {
636 /* for mpeg2 video, we want to know the real
637 frame rate, so we decode 40 frames. In mpeg
638 TS case we do not do it because it would be
639 too long */
640 st->codec_info_nb_real_frames++;
641 st->codec_info_nb_repeat_frames += st->codec.repeat_pict;
642 #if 0
643 /* XXX: testing */
644 if ((st->codec_info_nb_real_frames % 24) == 23) {
645 st->codec_info_nb_repeat_frames += 2;
646 }
647 #endif
648 /* stop after 40 frames */
649 if (st->codec_info_nb_real_frames >= 40) {
650 st->r_frame_rate = (st->codec.frame_rate *
651 st->codec_info_nb_real_frames) /
652 (st->codec_info_nb_real_frames +
653 (st->codec_info_nb_repeat_frames >> 1));
654 goto close_codec;
655 }
656 } else {
657 close_codec:
658 st->codec_info_state = CSTATE_FOUND;
659 avcodec_close(&st->codec);
660 }
661 break;
662 }
663 ptr += ret;
664 size -= ret;
665 }
666 }
667 count++;
668 }
669
670 /* close each codec if there are opened */
671 for(i=0;i<ic->nb_streams;i++) {
672 st = ic->streams[i];
673 if (st->codec_info_state == CSTATE_DECODING)
674 avcodec_close(&st->codec);
675 }
676
677 /* set real frame rate info */
678 for(i=0;i<ic->nb_streams;i++) {
679 st = ic->streams[i];
680 if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
681 if (!st->r_frame_rate)
682 st->r_frame_rate = st->codec.frame_rate;
683 }
684 }
685
686 return ret;
687 }
688
689 /**
690 * Close a media file (but not its codecs)
691 *
692 * @param s media file handle
693 */
694 void av_close_input_file(AVFormatContext *s)
695 {
696 int i;
697
698 if (s->iformat->read_close)
699 s->iformat->read_close(s);
700 for(i=0;i<s->nb_streams;i++) {
701 av_free(s->streams[i]);
702 }
703 if (s->packet_buffer) {
704 AVPacketList *p, *p1;
705 p = s->packet_buffer;
706 while (p != NULL) {
707 p1 = p->next;
708 av_free_packet(&p->pkt);
709 av_free(p);
710 p = p1;
711 }
712 s->packet_buffer = NULL;
713 }
714 if (!(s->iformat->flags & AVFMT_NOFILE)) {
715 url_fclose(&s->pb);
716 }
717 av_free(s->priv_data);
718 av_free(s);
719 }
720
721 /**
722 * Add a new stream to a media file. Can only be called in the
723 * read_header function. If the flag AVFMT_NOHEADER is in the format
724 * description, then new streams can be added in read_packet too.
725 *
726 *
727 * @param s media file handle
728 * @param id file format dependent stream id
729 */
730 AVStream *av_new_stream(AVFormatContext *s, int id)
731 {
732 AVStream *st;
733
734 if (s->nb_streams >= MAX_STREAMS)
735 return NULL;
736
737 st = av_mallocz(sizeof(AVStream));
738 if (!st)
739 return NULL;
740 st->index = s->nb_streams;
741 st->id = id;
742 s->streams[s->nb_streams++] = st;
743 return st;
744 }
745
746 /************************************************************/
747 /* output media file */
748
749 /**
750 * allocate the stream private data and write the stream header to an
751 * output media file
752 *
753 * @param s media file handle
754 * @return 0 if OK. AVERROR_xxx if error.
755 */
756 int av_write_header(AVFormatContext *s)
757 {
758 s->priv_data = av_mallocz(s->oformat->priv_data_size);
759 if (!s->priv_data)
760 return AVERROR_NOMEM;
761 return s->oformat->write_header(s);
762 }
763
764 /**
765 * write a packet to an output media file
766 *
767 * @param s media file handle
768 * @param pkt packet to write
769 * @param force_pts XXX: need to suppress that
770 */
771 int av_write_packet(AVFormatContext *s, AVPacket *pkt, int force_pts)
772 {
773 /* XXX: currently, an emulation because internal API must change */
774 return s->oformat->write_packet(s, pkt->stream_index, pkt->data, pkt->size, force_pts);
775 }
776
777 /**
778 * write the stream trailer to an output media file and and free the
779 * file private data.
780 *
781 * @param s media file handle
782 * @return 0 if OK. AVERROR_xxx if error. */
783 int av_write_trailer(AVFormatContext *s)
784 {
785 int ret;
786 ret = s->oformat->write_trailer(s);
787 av_freep(&s->priv_data);
788 return ret;
789 }
790
791 /* "user interface" functions */
792
793 void dump_format(AVFormatContext *ic,
794 int index,
795 const char *url,
796 int is_output)
797 {
798 int i, flags;
799 char buf[256];
800
801 fprintf(stderr, "%s #%d, %s, %s '%s':\n",
802 is_output ? "Output" : "Input",
803 index,
804 is_output ? ic->oformat->name : ic->iformat->name,
805 is_output ? "to" : "from", url);
806 for(i=0;i<ic->nb_streams;i++) {
807 AVStream *st = ic->streams[i];
808 avcodec_string(buf, sizeof(buf), &st->codec, is_output);
809 fprintf(stderr, " Stream #%d.%d", index, i);
810 /* the pid is an important information, so we display it */
811 /* XXX: add a generic system */
812 if (is_output)
813 flags = ic->oformat->flags;
814 else
815 flags = ic->iformat->flags;
816 if (flags & AVFMT_SHOW_IDS) {
817 fprintf(stderr, "[0x%x]", st->id);
818 }
819 fprintf(stderr, ": %s\n", buf);
820 }
821 }
822
823 typedef struct {
824 const char *str;
825 int width, height;
826 } SizeEntry;
827
828 static SizeEntry sizes[] = {
829 { "sqcif", 128, 96 },
830 { "qcif", 176, 144 },
831 { "cif", 352, 288 },
832 { "4cif", 704, 576 },
833 };
834
835 int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
836 {
837 int i;
838 int n = sizeof(sizes) / sizeof(SizeEntry);
839 const char *p;
840 int frame_width = 0, frame_height = 0;
841
842 for(i=0;i<n;i++) {
843 if (!strcmp(sizes[i].str, str)) {
844 frame_width = sizes[i].width;
845 frame_height = sizes[i].height;
846 break;
847 }
848 }
849 if (i == n) {
850 p = str;
851 frame_width = strtol(p, (char **)&p, 10);
852 if (*p)
853 p++;
854 frame_height = strtol(p, (char **)&p, 10);
855 }
856 if (frame_width <= 0 || frame_height <= 0)
857 return -1;
858 *width_ptr = frame_width;
859 *height_ptr = frame_height;
860 return 0;
861 }
862
863 INT64 gettime(void)
864 {
865 #ifdef CONFIG_WIN32
866 struct _timeb tb;
867 _ftime(&tb);
868 return ((INT64)tb.time * INT64_C(1000) + (INT64)tb.millitm) * INT64_C(1000);
869 #else
870 struct timeval tv;
871 gettimeofday(&tv,NULL);
872 return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
873 #endif
874 }
875
876 /* syntax: [YYYY-MM-DD ][[HH:]MM:]SS[.m...] . Return the date in micro seconds since 1970 */
877 INT64 parse_date(const char *datestr, int duration)
878 {
879 const char *p;
880 INT64 t;
881 int sec;
882
883 p = datestr;
884 if (!duration) {
885 static const UINT8 months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
886 int year, month, day, i;
887
888 if (strlen(p) >= 5 && p[4] == '-') {
889
890 year = strtol(p, (char **)&p, 10);
891 if (*p)
892 p++;
893 month = strtol(p, (char **)&p, 10) - 1;
894 if (*p)
895 p++;
896 day = strtol(p, (char **)&p, 10) - 1;
897 if (*p)
898 p++;
899 day += (year - 1970) * 365;
900 /* if >= March, take February of current year into account too */
901 if (month >= 2)
902 year++;
903 for(i=1970;i<year;i++) {
904 if ((i % 100) == 0) {
905 if ((i % 400) == 0) day++;
906 } else if ((i % 4) == 0) {
907 day++;
908 }
909 }
910 for(i=0;i<month;i++)
911 day += months[i];
912 } else {
913 day = (time(NULL) / (3600 * 24));
914 }
915 t = day * (3600 * 24);
916 } else {
917 t = 0;
918 }
919
920 sec = 0;
921 for(;;) {
922 int val;
923 val = strtol(p, (char **)&p, 10);
924 sec = sec * 60 + val;
925 if (*p != ':')
926 break;
927 p++;
928 }
929 t = (t + sec) * 1000000;
930 if (*p == '.') {
931 int val, n;
932 p++;
933 n = strlen(p);
934 if (n > 6)
935 n = 6;
936 val = strtol(p, NULL, 10);
937 while (n < 6) {
938 val = val * 10;
939 n++;
940 }
941 t += val;
942 }
943 return t;
944 }
945
946 /* syntax: '?tag1=val1&tag2=val2...'. No URL decoding is done. Return
947 1 if found */
948 int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
949 {
950 const char *p;
951 char tag[128], *q;
952
953 p = info;
954 if (*p == '?')
955 p++;
956 for(;;) {
957 q = tag;
958 while (*p != '\0' && *p != '=' && *p != '&') {
959 if ((q - tag) < sizeof(tag) - 1)
960 *q++ = *p;
961 p++;
962 }
963 *q = '\0';
964 q = arg;
965 if (*p == '=') {
966 p++;
967 while (*p != '&' && *p != '\0') {
968 if ((q - arg) < arg_size - 1)
969 *q++ = *p;
970 p++;
971 }
972 *q = '\0';
973 }
974 if (!strcmp(tag, tag1))
975 return 1;
976 if (*p != '&')
977 break;
978 p++;
979 }
980 return 0;
981 }
982
983 /* Return in 'buf' the path with '%d' replaced by number. Also handles
984 the '%0nd' format where 'n' is the total number of digits and
985 '%%'. Return 0 if OK, and -1 if format error */
986 int get_frame_filename(char *buf, int buf_size,
987 const char *path, int number)
988 {
989 const char *p;
990 char *q, buf1[20];
991 int nd, len, c, percentd_found;
992
993 q = buf;
994 p = path;
995 percentd_found = 0;
996 for(;;) {
997 c = *p++;
998 if (c == '\0')
999 break;
1000 if (c == '%') {
1001 nd = 0;
1002 while (*p >= '0' && *p <= '9') {
1003 nd = nd * 10 + *p++ - '0';
1004 }
1005 c = *p++;
1006 switch(c) {
1007 case '%':
1008 goto addchar;
1009 case 'd':
1010 if (percentd_found)
1011 goto fail;
1012 percentd_found = 1;
1013 snprintf(buf1, sizeof(buf1), "%0*d", nd, number);
1014 len = strlen(buf1);
1015 if ((q - buf + len) > buf_size - 1)
1016 goto fail;
1017 memcpy(q, buf1, len);
1018 q += len;
1019 break;
1020 default:
1021 goto fail;
1022 }
1023 } else {
1024 addchar:
1025 if ((q - buf) < buf_size - 1)
1026 *q++ = c;
1027 }
1028 }
1029 if (!percentd_found)
1030 goto fail;
1031 *q = '\0';
1032 return 0;
1033 fail:
1034 *q = '\0';
1035 return -1;
1036 }
1037
1038 static int gcd(INT64 a, INT64 b)
1039 {
1040 INT64 c;
1041
1042 while (1) {
1043 c = a % b;
1044 if (c == 0)
1045 return b;
1046 a = b;
1047 b = c;
1048 }
1049 }
1050
1051 void ticker_init(Ticker *tick, INT64 inrate, INT64 outrate)
1052 {
1053 int g;
1054
1055 g = gcd(inrate, outrate);
1056 inrate /= g;
1057 outrate /= g;
1058
1059 tick->value = -outrate/2;
1060
1061 tick->inrate = inrate;
1062 tick->outrate = outrate;
1063 tick->div = tick->outrate / tick->inrate;
1064 tick->mod = tick->outrate % tick->inrate;
1065 }
1066
1067 /**
1068 *
1069 * Print on stdout a nice hexa dump of a buffer
1070 * @param buf buffer
1071 * @param size buffer size
1072 */
1073 void av_hex_dump(UINT8 *buf, int size)
1074 {
1075 int len, i, j, c;
1076
1077 for(i=0;i<size;i+=16) {
1078 len = size - i;
1079 if (len > 16)
1080 len = 16;
1081 printf("%08x ", i);
1082 for(j=0;j<16;j++) {
1083 if (j < len)
1084 printf(" %02x", buf[i+j]);
1085 else
1086 printf(" ");
1087 }
1088 printf(" ");
1089 for(j=0;j<len;j++) {
1090 c = buf[i+j];
1091 if (c < ' ' || c > '~')
1092 c = '.';
1093 printf("%c", c);
1094 }
1095 printf("\n");
1096 }
1097 }
1098