Statistics
| Branch: | Revision:

ffmpeg / libav / utils.c @ 6775c758

History | View | Annotate | Download (12.5 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 <stdlib.h>
20
#include <stdio.h>
21
#include <string.h>
22
#include <unistd.h>
23
#include <fcntl.h>
24
#include <errno.h>
25
#include <sys/time.h>
26
#include <time.h>
27

    
28
#include "avformat.h"
29

    
30
AVFormat *first_format;
31

    
32
void register_avformat(AVFormat *format)
33
{
34
    AVFormat **p;
35
    p = &first_format;
36
    while (*p != NULL) p = &(*p)->next;
37
    *p = format;
38
    format->next = NULL;
39
}
40

    
41
int match_ext(const char *filename, const char *extensions)
42
{
43
    const char *ext, *p;
44
    char ext1[32], *q;
45

    
46
    ext = strrchr(filename, '.');
47
    if (ext) {
48
        ext++;
49
        p = extensions;
50
        for(;;) {
51
            q = ext1;
52
            while (*p != '\0' && *p != ',') 
53
                *q++ = *p++;
54
            *q = '\0';
55
            if (!strcasecmp(ext1, ext)) 
56
                return 1;
57
            if (*p == '\0') 
58
                break;
59
            p++;
60
        }
61
    }
62
    return 0;
63
}
64

    
65
AVFormat *guess_format(const char *short_name, const char *filename, const char *mime_type)
66
{
67
    AVFormat *fmt, *fmt_found;
68
    int score_max, score;
69

    
70
    /* find the proper file type */
71
    fmt_found = NULL;
72
    score_max = 0;
73
    fmt = first_format;
74
    while (fmt != NULL) {
75
        score = 0;
76
        if (fmt->name && short_name && !strcmp(fmt->name, short_name))
77
            score += 100;
78
        if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
79
            score += 10;
80
        if (filename && fmt->extensions && 
81
            match_ext(filename, fmt->extensions)) {
82
            score += 5;
83
        }
84
        if (score > score_max) {
85
            score_max = score;
86
            fmt_found = fmt;
87
        }
88
        fmt = fmt->next;
89
    }
90
    return fmt_found;
91
}   
92

    
93
/* return TRUE if val is a prefix of str. If it returns TRUE, ptr is
94
   set to the next character in 'str' after the prefix */
95
int strstart(const char *str, const char *val, const char **ptr)
96
{
97
    const char *p, *q;
98
    p = str;
99
    q = val;
100
    while (*q != '\0') {
101
        if (*p != *q)
102
            return 0;
103
        p++;
104
        q++;
105
    }
106
    if (ptr)
107
        *ptr = p;
108
    return 1;
109
}
110

    
111
void nstrcpy(char *buf, int buf_size, const char *str)
112
{
113
    int c;
114
    char *q = buf;
115

    
116
    for(;;) {
117
        c = *str++;
118
        if (c == 0 || q >= buf + buf_size - 1)
119
            break;
120
        *q++ = c;
121
    }
122
    *q = '\0';
123
}
124

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

    
130
    register_avformat(&mp2_format);
131
    register_avformat(&ac3_format);
132
    register_avformat(&mpeg_mux_format);
133
    register_avformat(&mpeg1video_format);
134
    register_avformat(&h263_format);
135
    register_avformat(&rm_format);
136
    register_avformat(&asf_format);
137
    register_avformat(&avi_format);
138
    register_avformat(&mpjpeg_format);
139
    register_avformat(&jpeg_format);
140
    register_avformat(&swf_format);
141
    register_avformat(&wav_format);
142
    register_avformat(&pcm_format);
143
    register_avformat(&rawvideo_format);
144
    register_avformat(&ffm_format);
145
    register_avformat(&pgm_format);
146
    register_avformat(&ppm_format);
147
    register_avformat(&pgmyuv_format);
148
    register_avformat(&imgyuv_format);
149
    register_avformat(&pgmpipe_format);
150
    register_avformat(&pgmyuvpipe_format);
151
    register_avformat(&ppmpipe_format);
152

    
153
    register_protocol(&file_protocol);
154
    register_protocol(&pipe_protocol);
155
    register_protocol(&audio_protocol);
156
    register_protocol(&video_protocol);
157
    register_protocol(&udp_protocol);
158
    register_protocol(&http_protocol);
159
}
160

    
161
/* memory handling */
162

    
163
int av_new_packet(AVPacket *pkt, int size)
164
{
165
    pkt->data = malloc(size);
166
    if (!pkt->data)
167
        return -ENOMEM;
168
    pkt->size = size;
169
    /* sane state */
170
    pkt->pts = 0;
171
    pkt->stream_index = 0;
172
    pkt->flags = 0;
173
    return 0;
174
}
175

    
176
void av_free_packet(AVPacket *pkt)
177
{
178
    free(pkt->data);
179
    /* fail safe */
180
    pkt->data = NULL;
181
    pkt->size = 0;
182
}
183

    
184
/* fifo handling */
185

    
186
int fifo_init(FifoBuffer *f, int size)
187
{
188
    f->buffer = malloc(size);
189
    if (!f->buffer)
190
        return -1;
191
    f->end = f->buffer + size;
192
    f->wptr = f->rptr = f->buffer;
193
    return 0;
194
}
195

    
196
void fifo_free(FifoBuffer *f)
197
{
198
    free(f->buffer);
199
}
200

    
201
int fifo_size(FifoBuffer *f, UINT8 *rptr)
202
{
203
    int size;
204

    
205
    if (f->wptr >= rptr) {
206
        size = f->wptr - rptr;
207
    } else {
208
        size = (f->end - rptr) + (f->wptr - f->buffer);
209
    }
210
    return size;
211
}
212

    
213
/* get data from the fifo (return -1 if not enough data) */
214
int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr)
215
{
216
    UINT8 *rptr = *rptr_ptr;
217
    int size, len;
218

    
219
    if (f->wptr >= rptr) {
220
        size = f->wptr - rptr;
221
    } else {
222
        size = (f->end - rptr) + (f->wptr - f->buffer);
223
    }
224
    
225
    if (size < buf_size)
226
        return -1;
227
    while (buf_size > 0) {
228
        len = f->end - rptr;
229
        if (len > buf_size)
230
            len = buf_size;
231
        memcpy(buf, rptr, len);
232
        buf += len;
233
        rptr += len;
234
        if (rptr >= f->end)
235
            rptr = f->buffer;
236
        buf_size -= len;
237
    }
238
    *rptr_ptr = rptr;
239
    return 0;
240
}
241

    
242
void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr)
243
{
244
    int len;
245
    UINT8 *wptr;
246
    wptr = *wptr_ptr;
247
    while (size > 0) {
248
        len = f->end - wptr;
249
        if (len > size)
250
            len = size;
251
        memcpy(wptr, buf, len);
252
        wptr += len;
253
        if (wptr >= f->end)
254
            wptr = f->buffer;
255
        buf += len;
256
        size -= len;
257
    }
258
    *wptr_ptr = wptr;
259
}
260

    
261
/* media file handling */
262

    
263
AVFormatContext *av_open_input_file(const char *filename, int buf_size)
264
{
265
    AVFormatParameters params, *ap;
266
    AVFormat *fmt;
267
    AVFormatContext *ic = NULL;
268
    URLFormat url_format;
269
    int err;
270

    
271
    ic = av_mallocz(sizeof(AVFormatContext));
272
    if (!ic)
273
        goto fail;
274
    if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0)
275
        goto fail;
276
    
277
    if (buf_size > 0) {
278
        url_setbufsize(&ic->pb, buf_size);
279
    }
280

    
281
    /* find format */
282
    err = url_getformat(url_fileno(&ic->pb), &url_format);
283
    if (err >= 0) {
284
        fmt = guess_format(url_format.format_name, NULL, NULL);
285
        ap = &params;
286
        ap->sample_rate = url_format.sample_rate;
287
        ap->frame_rate = url_format.frame_rate;
288
        ap->channels = url_format.channels;
289
        ap->width = url_format.width;
290
        ap->height = url_format.height;
291
        ap->pix_fmt = url_format.pix_fmt;
292
    } else {
293
        fmt = guess_format(NULL, filename, NULL);
294
        ap = NULL;
295
    }
296
    if (!fmt || !fmt->read_header) {
297
        return NULL;
298
    }
299
    ic->format = fmt;
300

    
301
    err = ic->format->read_header(ic, ap);
302
    if (err < 0) {
303
        url_fclose(&ic->pb);
304
        goto fail;
305
    }
306
    
307
    return ic;
308

    
309
 fail:
310
    if (ic)
311
        free(ic);
312
    return NULL;
313
}
314

    
315
int av_read_packet(AVFormatContext *s, AVPacket *pkt)
316
{
317
    AVPacketList *pktl;
318

    
319
    pktl = s->packet_buffer;
320
    if (pktl) {
321
        /* read packet from packet buffer, if there is data */
322
        *pkt = pktl->pkt;
323
        s->packet_buffer = pktl->next;
324
        free(pktl);
325
        return 0;
326
    } else {
327
        return s->format->read_packet(s, pkt);
328
    }
329
}
330

    
331
void av_close_input_file(AVFormatContext *s)
332
{
333
    int i;
334

    
335
    if (s->format->read_close)
336
        s->format->read_close(s);
337
    for(i=0;i<s->nb_streams;i++) {
338
        free(s->streams[i]);
339
    }
340
    if (s->packet_buffer) {
341
        AVPacketList *p, *p1;
342
        p = s->packet_buffer;
343
        while (p != NULL) {
344
            p1 = p->next;
345
            av_free_packet(&p->pkt);
346
            free(p);
347
            p = p1;
348
        }
349
        s->packet_buffer = NULL;
350
    }
351
    url_fclose(&s->pb);
352
    free(s);
353
}
354

    
355

    
356
int av_write_packet(AVFormatContext *s, AVPacket *pkt)
357
{
358
    /* XXX: currently, an emulation because internal API must change */
359
    return s->format->write_packet(s, pkt->stream_index, pkt->data, pkt->size);
360
}
361

    
362
/* "user interface" functions */
363

    
364
void dump_format(AVFormatContext *ic,
365
                 int index, 
366
                 const char *url,
367
                 int is_output)
368
{
369
    int i;
370
    char buf[256];
371

    
372
    fprintf(stderr, "%s #%d, %s, %s '%s':\n", 
373
            is_output ? "Output" : "Input",
374
            index, ic->format->name, 
375
            is_output ? "to" : "from", url);
376
    for(i=0;i<ic->nb_streams;i++) {
377
        AVStream *st = ic->streams[i];
378
        avcodec_string(buf, sizeof(buf), &st->codec, is_output);
379
        fprintf(stderr, "  Stream #%d.%d: %s\n", index, i, buf);
380
    }
381
}
382

    
383
typedef struct {
384
    const char *str;
385
    int width, height;
386
} SizeEntry;
387

    
388
static SizeEntry sizes[] = {
389
    { "sqcif", 128, 96 },
390
    { "qcif", 176, 144 },
391
    { "cif", 352, 288 },
392
    { "4cif", 704, 576 },
393
};
394
    
395
int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
396
{
397
    int i;
398
    int n = sizeof(sizes) / sizeof(SizeEntry);
399
    const char *p;
400
    int frame_width = 0, frame_height = 0;
401

    
402
    for(i=0;i<n;i++) {
403
        if (!strcmp(sizes[i].str, str)) {
404
            frame_width = sizes[i].width;
405
            frame_height = sizes[i].height;
406
            break;
407
        }
408
    }
409
    if (i == n) {
410
        p = str;
411
        frame_width = strtol(p, (char **)&p, 10);
412
        if (*p)
413
            p++;
414
        frame_height = strtol(p, (char **)&p, 10);
415
    }
416
    if (frame_width <= 0 || frame_height <= 0)
417
        return -1;
418
    *width_ptr = frame_width;
419
    *height_ptr = frame_height;
420
    return 0;
421
}
422

    
423
INT64 gettime(void)
424
{
425
    struct timeval tv;
426
    gettimeofday(&tv,NULL);
427
    return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
428
}
429

    
430
/* syntax: [YYYY-MM-DD ][[HH:]MM:]SS[.m...] . Return the date in micro seconds since 1970 */
431
INT64 parse_date(const char *datestr, int duration)
432
{
433
    const char *p;
434
    INT64 t;
435
    int sec;
436

    
437
    p = datestr;
438
    if (!duration) {
439
        static const UINT8 months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
440
        int year, month, day, i;
441

    
442
        if (strlen(p) >= 5 && p[4] == '-') {
443
            
444
            year = strtol(p, (char **)&p, 10);
445
            if (*p)
446
                p++;
447
            month = strtol(p, (char **)&p, 10) - 1;
448
            if (*p)
449
                p++;
450
            day = strtol(p, (char **)&p, 10) - 1;
451
            if (*p)
452
                p++;
453
            day += (year - 1970) * 365;
454
            /* if >= March, take February of current year into account too */
455
            if (month >= 2)
456
                year++;
457
            for(i=1970;i<year;i++) {
458
                if ((i % 100) == 0) {
459
                    if ((i % 400) == 0) day++;
460
                } else if ((i % 4) == 0) {
461
                    day++;
462
                }
463
            }
464
            for(i=0;i<month;i++)
465
                day += months[i];
466
        } else {
467
            day = (time(NULL) / (3600 * 24));
468
        }
469
        t = day * (3600 * 24);
470
    } else {
471
        t = 0;
472
    }
473
    
474
    sec = 0;
475
    for(;;) {
476
        int val;
477
        val = strtol(p, (char **)&p, 10);
478
        sec = sec * 60 + val;
479
        if (*p != ':')
480
            break;
481
        p++;
482
    }
483
    t = (t + sec) * 1000000;
484
    if (*p == '.') {
485
        int val, n;
486
        p++;
487
        n = strlen(p);
488
        if (n > 6)
489
            n = 6;
490
        val = strtol(p, NULL, 10);
491
        while (n < 6) {
492
            val = val * 10;
493
            n++;
494
        }
495
        t += val;
496
    }
497
    return t;
498
}
499

    
500
/* syntax: '?tag1=val1&tag2=val2...'. No URL decoding is done. Return
501
   1 if found */
502
int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
503
{
504
    const char *p;
505
    char tag[128], *q;
506

    
507
    p = info;
508
    if (*p == '?')
509
        p++;
510
    for(;;) {
511
        q = tag;
512
        while (*p != '\0' && *p != '=' && *p != '&') {
513
            if ((q - tag) < sizeof(tag) - 1)
514
                *q++ = *p;
515
            p++;
516
        }
517
        *q = '\0';
518
        q = arg;
519
        if (*p == '=') {
520
            p++;
521
            while (*p != '&' && *p != '\0') {
522
                if ((q - arg) < arg_size - 1)
523
                    *q++ = *p;
524
                p++;
525
            }
526
            *q = '\0';
527
        }
528
        if (!strcmp(tag, tag1)) 
529
            return 1;
530
        if (*p != '&')
531
            break;
532
    }
533
    return 0;
534
}
535