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