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