Statistics
| Branch: | Revision:

ffmpeg / libav / utils.c @ 9150f42e

History | View | Annotate | Download (14.2 KB)

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
 */
19
#include "avformat.h"
20
#ifndef CONFIG_WIN32
21
#include <unistd.h>
22
#include <fcntl.h>
23
#include <sys/time.h>
24
#include <time.h>
25
#else
26
#define strcasecmp _stricmp
27
#include <sys/types.h>
28
#include <sys/timeb.h>
29
#endif
30

    
31
AVFormat *first_format;
32

    
33
void 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

    
42
int 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

    
66
AVFormat *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 */
96
int 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

    
112
void 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

    
126
void register_all(void)
127
{
128
    avcodec_init();
129
    avcodec_register_all();
130

    
131
    register_avformat(&mp2_format);
132
    register_avformat(&ac3_format);
133
    register_avformat(&mpeg_mux_format);
134
    register_avformat(&mpeg1video_format);
135
    register_avformat(&mjpeg_format);
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);
142
    register_avformat(&single_jpeg_format);
143
    register_avformat(&swf_format);
144
    register_avformat(&wav_format);
145
    register_avformat(&pcm_format);
146
    register_avformat(&rawvideo_format);
147
#ifndef CONFIG_WIN32
148
    register_avformat(&ffm_format);
149
#endif
150
    register_avformat(&pgm_format);
151
    register_avformat(&ppm_format);
152
    register_avformat(&pgmyuv_format);
153
    register_avformat(&imgyuv_format);
154
    register_avformat(&pgmpipe_format);
155
    register_avformat(&pgmyuvpipe_format);
156
    register_avformat(&ppmpipe_format);
157

    
158
    register_protocol(&file_protocol);
159
    register_protocol(&pipe_protocol);
160
#ifdef CONFIG_GRAB
161
    register_protocol(&audio_protocol);
162
    register_protocol(&video_protocol);
163
#endif
164
#ifndef CONFIG_WIN32
165
    register_protocol(&udp_protocol);
166
    register_protocol(&http_protocol);
167
#endif
168
}
169

    
170
/* memory handling */
171

    
172
int 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

    
185
void 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

    
195
int 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

    
205
void fifo_free(FifoBuffer *f)
206
{
207
    free(f->buffer);
208
}
209

    
210
int 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) */
223
int 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

    
251
void 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

    
272
AVFormatContext *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

    
324
int 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

    
340
void 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

    
365
int 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

    
373
void 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

    
392
typedef struct {
393
    const char *str;
394
    int width, height;
395
} SizeEntry;
396

    
397
static SizeEntry sizes[] = {
398
    { "sqcif", 128, 96 },
399
    { "qcif", 176, 144 },
400
    { "cif", 352, 288 },
401
    { "4cif", 704, 576 },
402
};
403
    
404
int 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

    
432
INT64 gettime(void)
433
{
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
439
    struct timeval tv;
440
    gettimeofday(&tv,NULL);
441
    return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
442
#endif
443
}
444

    
445
/* syntax: [YYYY-MM-DD ][[HH:]MM:]SS[.m...] . Return the date in micro seconds since 1970 */
446
INT64 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 */
517
int 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

    
551
/* Return in 'buf' the path with '%d' replaced by number. Also handles
552
   the '%0nd' format where 'n' is the total number of digits and
553
   '%%'. Return 0 if OK, and -1 if format error */
554
int get_frame_filename(char *buf, int buf_size,
555
                       const char *path, int number)
556
{
557
    const char *p;
558
    char *q, buf1[20];
559
    int nd, len, c, percentd_found;
560

    
561
    q = buf;
562
    p = path;
563
    percentd_found = 0;
564
    for(;;) {
565
        c = *p++;
566
        if (c == '\0')
567
            break;
568
        if (c == '%') {
569
            nd = 0;
570
            while (*p >= '0' && *p <= '9') {
571
                nd = nd * 10 + *p++ - '0';
572
            }
573
            c = *p++;
574
            switch(c) {
575
            case '%':
576
                goto addchar;
577
            case 'd':
578
                if (percentd_found)
579
                    goto fail;
580
                percentd_found = 1;
581
                snprintf(buf1, sizeof(buf1), "%0*d", nd, number);
582
                len = strlen(buf1);
583
                if ((q - buf + len) > buf_size - 1)
584
                    goto fail;
585
                memcpy(q, buf1, len);
586
                q += len;
587
                break;
588
            default:
589
                goto fail;
590
            }
591
        } else {
592
        addchar:
593
            if ((q - buf) < buf_size - 1)
594
                *q++ = c;
595
        }
596
    }
597
    if (!percentd_found)
598
        goto fail;
599
    *q = '\0';
600
    return 0;
601
 fail:
602
    *q = '\0';
603
    return -1;
604
}
605

    
606