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