restore audio settings - use all the frame buffers provided by the driver
[libav.git] / libav / utils.c
CommitLineData
de6d9b64
FB
1/*
2 * Various utilities for ffmpeg system
3 * Copyright (c) 2000,2001 Gerard Lantau
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
8be1c656
FB
19#include "avformat.h"
20#ifndef CONFIG_WIN32
de6d9b64
FB
21#include <unistd.h>
22#include <fcntl.h>
de6d9b64
FB
23#include <sys/time.h>
24#include <time.h>
8be1c656
FB
25#else
26#define strcasecmp _stricmp
27#include <sys/types.h>
28#include <sys/timeb.h>
29#endif
de6d9b64
FB
30
31AVFormat *first_format;
32
33void register_avformat(AVFormat *format)
34{
35 AVFormat **p;
36 p = &first_format;
37 while (*p != NULL) p = &(*p)->next;
38 *p = format;
39 format->next = NULL;
40}
41
42int match_ext(const char *filename, const char *extensions)
43{
44 const char *ext, *p;
45 char ext1[32], *q;
46
47 ext = strrchr(filename, '.');
48 if (ext) {
49 ext++;
50 p = extensions;
51 for(;;) {
52 q = ext1;
53 while (*p != '\0' && *p != ',')
54 *q++ = *p++;
55 *q = '\0';
56 if (!strcasecmp(ext1, ext))
57 return 1;
58 if (*p == '\0')
59 break;
60 p++;
61 }
62 }
63 return 0;
64}
65
66AVFormat *guess_format(const char *short_name, const char *filename, const char *mime_type)
67{
68 AVFormat *fmt, *fmt_found;
69 int score_max, score;
70
71 /* find the proper file type */
72 fmt_found = NULL;
73 score_max = 0;
74 fmt = first_format;
75 while (fmt != NULL) {
76 score = 0;
77 if (fmt->name && short_name && !strcmp(fmt->name, short_name))
78 score += 100;
79 if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
80 score += 10;
81 if (filename && fmt->extensions &&
82 match_ext(filename, fmt->extensions)) {
83 score += 5;
84 }
85 if (score > score_max) {
86 score_max = score;
87 fmt_found = fmt;
88 }
89 fmt = fmt->next;
90 }
91 return fmt_found;
92}
93
94/* return TRUE if val is a prefix of str. If it returns TRUE, ptr is
95 set to the next character in 'str' after the prefix */
96int strstart(const char *str, const char *val, const char **ptr)
97{
98 const char *p, *q;
99 p = str;
100 q = val;
101 while (*q != '\0') {
102 if (*p != *q)
103 return 0;
104 p++;
105 q++;
106 }
107 if (ptr)
108 *ptr = p;
109 return 1;
110}
111
112void nstrcpy(char *buf, int buf_size, const char *str)
113{
114 int c;
115 char *q = buf;
116
117 for(;;) {
118 c = *str++;
119 if (c == 0 || q >= buf + buf_size - 1)
120 break;
121 *q++ = c;
122 }
123 *q = '\0';
124}
125
126void register_all(void)
127{
128 avcodec_init();
129 avcodec_register_all();
de6d9b64
FB
130
131 register_avformat(&mp2_format);
132 register_avformat(&ac3_format);
133 register_avformat(&mpeg_mux_format);
134 register_avformat(&mpeg1video_format);
27e084bd 135 register_avformat(&mjpeg_format);
de6d9b64
FB
136 register_avformat(&h263_format);
137 register_avformat(&rm_format);
138 register_avformat(&asf_format);
139 register_avformat(&avi_format);
140 register_avformat(&mpjpeg_format);
141 register_avformat(&jpeg_format);
27e084bd 142 register_avformat(&single_jpeg_format);
de6d9b64
FB
143 register_avformat(&swf_format);
144 register_avformat(&wav_format);
145 register_avformat(&pcm_format);
146 register_avformat(&rawvideo_format);
8be1c656 147#ifndef CONFIG_WIN32
de6d9b64 148 register_avformat(&ffm_format);
8be1c656 149#endif
de6d9b64 150 register_avformat(&pgm_format);
6775c758 151 register_avformat(&ppm_format);
de6d9b64
FB
152 register_avformat(&pgmyuv_format);
153 register_avformat(&imgyuv_format);
154 register_avformat(&pgmpipe_format);
6775c758
FB
155 register_avformat(&pgmyuvpipe_format);
156 register_avformat(&ppmpipe_format);
de6d9b64
FB
157
158 register_protocol(&file_protocol);
159 register_protocol(&pipe_protocol);
8be1c656 160#ifdef CONFIG_GRAB
de6d9b64
FB
161 register_protocol(&audio_protocol);
162 register_protocol(&video_protocol);
8be1c656
FB
163#endif
164#ifndef CONFIG_WIN32
de6d9b64
FB
165 register_protocol(&udp_protocol);
166 register_protocol(&http_protocol);
8be1c656 167#endif
de6d9b64
FB
168}
169
170/* memory handling */
171
172int av_new_packet(AVPacket *pkt, int size)
173{
174 pkt->data = malloc(size);
175 if (!pkt->data)
176 return -ENOMEM;
177 pkt->size = size;
178 /* sane state */
179 pkt->pts = 0;
180 pkt->stream_index = 0;
181 pkt->flags = 0;
182 return 0;
183}
184
185void av_free_packet(AVPacket *pkt)
186{
187 free(pkt->data);
188 /* fail safe */
189 pkt->data = NULL;
190 pkt->size = 0;
191}
192
193/* fifo handling */
194
195int fifo_init(FifoBuffer *f, int size)
196{
197 f->buffer = malloc(size);
198 if (!f->buffer)
199 return -1;
200 f->end = f->buffer + size;
201 f->wptr = f->rptr = f->buffer;
202 return 0;
203}
204
205void fifo_free(FifoBuffer *f)
206{
207 free(f->buffer);
208}
209
210int fifo_size(FifoBuffer *f, UINT8 *rptr)
211{
212 int size;
213
214 if (f->wptr >= rptr) {
215 size = f->wptr - rptr;
216 } else {
217 size = (f->end - rptr) + (f->wptr - f->buffer);
218 }
219 return size;
220}
221
222/* get data from the fifo (return -1 if not enough data) */
223int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr)
224{
225 UINT8 *rptr = *rptr_ptr;
226 int size, len;
227
228 if (f->wptr >= rptr) {
229 size = f->wptr - rptr;
230 } else {
231 size = (f->end - rptr) + (f->wptr - f->buffer);
232 }
233
234 if (size < buf_size)
235 return -1;
236 while (buf_size > 0) {
237 len = f->end - rptr;
238 if (len > buf_size)
239 len = buf_size;
240 memcpy(buf, rptr, len);
241 buf += len;
242 rptr += len;
243 if (rptr >= f->end)
244 rptr = f->buffer;
245 buf_size -= len;
246 }
247 *rptr_ptr = rptr;
248 return 0;
249}
250
251void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr)
252{
253 int len;
254 UINT8 *wptr;
255 wptr = *wptr_ptr;
256 while (size > 0) {
257 len = f->end - wptr;
258 if (len > size)
259 len = size;
260 memcpy(wptr, buf, len);
261 wptr += len;
262 if (wptr >= f->end)
263 wptr = f->buffer;
264 buf += len;
265 size -= len;
266 }
267 *wptr_ptr = wptr;
268}
269
270/* media file handling */
271
272AVFormatContext *av_open_input_file(const char *filename, int buf_size)
273{
274 AVFormatParameters params, *ap;
275 AVFormat *fmt;
276 AVFormatContext *ic = NULL;
277 URLFormat url_format;
278 int err;
279
280 ic = av_mallocz(sizeof(AVFormatContext));
281 if (!ic)
282 goto fail;
283 if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0)
284 goto fail;
285
286 if (buf_size > 0) {
287 url_setbufsize(&ic->pb, buf_size);
288 }
289
290 /* find format */
291 err = url_getformat(url_fileno(&ic->pb), &url_format);
292 if (err >= 0) {
293 fmt = guess_format(url_format.format_name, NULL, NULL);
294 ap = &params;
295 ap->sample_rate = url_format.sample_rate;
296 ap->frame_rate = url_format.frame_rate;
297 ap->channels = url_format.channels;
298 ap->width = url_format.width;
299 ap->height = url_format.height;
300 ap->pix_fmt = url_format.pix_fmt;
301 } else {
302 fmt = guess_format(NULL, filename, NULL);
303 ap = NULL;
304 }
305 if (!fmt || !fmt->read_header) {
306 return NULL;
307 }
308 ic->format = fmt;
309
310 err = ic->format->read_header(ic, ap);
311 if (err < 0) {
312 url_fclose(&ic->pb);
313 goto fail;
314 }
315
316 return ic;
317
318 fail:
319 if (ic)
320 free(ic);
321 return NULL;
322}
323
324int av_read_packet(AVFormatContext *s, AVPacket *pkt)
325{
326 AVPacketList *pktl;
327
328 pktl = s->packet_buffer;
329 if (pktl) {
330 /* read packet from packet buffer, if there is data */
331 *pkt = pktl->pkt;
332 s->packet_buffer = pktl->next;
333 free(pktl);
334 return 0;
335 } else {
336 return s->format->read_packet(s, pkt);
337 }
338}
339
340void av_close_input_file(AVFormatContext *s)
341{
342 int i;
343
344 if (s->format->read_close)
345 s->format->read_close(s);
346 for(i=0;i<s->nb_streams;i++) {
347 free(s->streams[i]);
348 }
349 if (s->packet_buffer) {
350 AVPacketList *p, *p1;
351 p = s->packet_buffer;
352 while (p != NULL) {
353 p1 = p->next;
354 av_free_packet(&p->pkt);
355 free(p);
356 p = p1;
357 }
358 s->packet_buffer = NULL;
359 }
360 url_fclose(&s->pb);
361 free(s);
362}
363
364
365int av_write_packet(AVFormatContext *s, AVPacket *pkt)
366{
367 /* XXX: currently, an emulation because internal API must change */
368 return s->format->write_packet(s, pkt->stream_index, pkt->data, pkt->size);
369}
370
371/* "user interface" functions */
372
373void dump_format(AVFormatContext *ic,
374 int index,
375 const char *url,
376 int is_output)
377{
378 int i;
379 char buf[256];
380
381 fprintf(stderr, "%s #%d, %s, %s '%s':\n",
382 is_output ? "Output" : "Input",
383 index, ic->format->name,
384 is_output ? "to" : "from", url);
385 for(i=0;i<ic->nb_streams;i++) {
386 AVStream *st = ic->streams[i];
387 avcodec_string(buf, sizeof(buf), &st->codec, is_output);
388 fprintf(stderr, " Stream #%d.%d: %s\n", index, i, buf);
389 }
390}
391
392typedef struct {
393 const char *str;
394 int width, height;
395} SizeEntry;
396
397static SizeEntry sizes[] = {
398 { "sqcif", 128, 96 },
399 { "qcif", 176, 144 },
400 { "cif", 352, 288 },
401 { "4cif", 704, 576 },
402};
403
404int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
405{
406 int i;
407 int n = sizeof(sizes) / sizeof(SizeEntry);
408 const char *p;
409 int frame_width = 0, frame_height = 0;
410
411 for(i=0;i<n;i++) {
412 if (!strcmp(sizes[i].str, str)) {
413 frame_width = sizes[i].width;
414 frame_height = sizes[i].height;
415 break;
416 }
417 }
418 if (i == n) {
419 p = str;
420 frame_width = strtol(p, (char **)&p, 10);
421 if (*p)
422 p++;
423 frame_height = strtol(p, (char **)&p, 10);
424 }
425 if (frame_width <= 0 || frame_height <= 0)
426 return -1;
427 *width_ptr = frame_width;
428 *height_ptr = frame_height;
429 return 0;
430}
431
432INT64 gettime(void)
433{
8be1c656
FB
434#ifdef CONFIG_WIN32
435 struct _timeb tb;
436 _ftime(&tb);
437 return ((INT64)tb.time * INT64_C(1000) + (INT64)tb.millitm) * INT64_C(1000);
438#else
de6d9b64
FB
439 struct timeval tv;
440 gettimeofday(&tv,NULL);
441 return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
8be1c656 442#endif
de6d9b64
FB
443}
444
445/* syntax: [YYYY-MM-DD ][[HH:]MM:]SS[.m...] . Return the date in micro seconds since 1970 */
446INT64 parse_date(const char *datestr, int duration)
447{
448 const char *p;
449 INT64 t;
450 int sec;
451
452 p = datestr;
453 if (!duration) {
454 static const UINT8 months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
455 int year, month, day, i;
456
457 if (strlen(p) >= 5 && p[4] == '-') {
458
459 year = strtol(p, (char **)&p, 10);
460 if (*p)
461 p++;
462 month = strtol(p, (char **)&p, 10) - 1;
463 if (*p)
464 p++;
465 day = strtol(p, (char **)&p, 10) - 1;
466 if (*p)
467 p++;
468 day += (year - 1970) * 365;
469 /* if >= March, take February of current year into account too */
470 if (month >= 2)
471 year++;
472 for(i=1970;i<year;i++) {
473 if ((i % 100) == 0) {
474 if ((i % 400) == 0) day++;
475 } else if ((i % 4) == 0) {
476 day++;
477 }
478 }
479 for(i=0;i<month;i++)
480 day += months[i];
481 } else {
482 day = (time(NULL) / (3600 * 24));
483 }
484 t = day * (3600 * 24);
485 } else {
486 t = 0;
487 }
488
489 sec = 0;
490 for(;;) {
491 int val;
492 val = strtol(p, (char **)&p, 10);
493 sec = sec * 60 + val;
494 if (*p != ':')
495 break;
496 p++;
497 }
498 t = (t + sec) * 1000000;
499 if (*p == '.') {
500 int val, n;
501 p++;
502 n = strlen(p);
503 if (n > 6)
504 n = 6;
505 val = strtol(p, NULL, 10);
506 while (n < 6) {
507 val = val * 10;
508 n++;
509 }
510 t += val;
511 }
512 return t;
513}
514
515/* syntax: '?tag1=val1&tag2=val2...'. No URL decoding is done. Return
516 1 if found */
517int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
518{
519 const char *p;
520 char tag[128], *q;
521
522 p = info;
523 if (*p == '?')
524 p++;
525 for(;;) {
526 q = tag;
527 while (*p != '\0' && *p != '=' && *p != '&') {
528 if ((q - tag) < sizeof(tag) - 1)
529 *q++ = *p;
530 p++;
531 }
532 *q = '\0';
533 q = arg;
534 if (*p == '=') {
535 p++;
536 while (*p != '&' && *p != '\0') {
537 if ((q - arg) < arg_size - 1)
538 *q++ = *p;
539 p++;
540 }
541 *q = '\0';
542 }
543 if (!strcmp(tag, tag1))
544 return 1;
545 if (*p != '&')
546 break;
547 }
548 return 0;
549}
550