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