Statistics
| Branch: | Revision:

ffmpeg / libav / utils.c @ 6cea494e

History | View | Annotate | Download (15.4 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
#include "tick.h"
21
#ifndef CONFIG_WIN32
22
#include <unistd.h>
23
#include <fcntl.h>
24
#include <sys/time.h>
25
#include <time.h>
26
#else
27
#define strcasecmp _stricmp
28
#include <sys/types.h>
29
#include <sys/timeb.h>
30
#endif
31

    
32
AVFormat *first_format;
33

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

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

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

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

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

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

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

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

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

    
132
    register_avformat(&mp2_format);
133
    register_avformat(&ac3_format);
134
    register_avformat(&mpeg_mux_format);
135
    register_avformat(&mpeg1video_format);
136
    register_avformat(&mjpeg_format);
137
    register_avformat(&h263_format);
138
    register_avformat(&rm_format);
139
    register_avformat(&asf_format);
140
    register_avformat(&avi_format);
141
    register_avformat(&mov_format);
142
    register_avformat(&mp4_format);
143
    register_avformat(&mpjpeg_format);
144
    register_avformat(&jpeg_format);
145
    register_avformat(&single_jpeg_format);
146
    register_avformat(&swf_format);
147
    register_avformat(&gif_format);
148
    register_avformat(&au_format);
149
    register_avformat(&wav_format);
150
    register_avformat(&pcm_s16le_format);
151
    register_avformat(&pcm_s16be_format);
152
    register_avformat(&pcm_u16le_format);
153
    register_avformat(&pcm_u16be_format);
154
    register_avformat(&pcm_s8_format);
155
    register_avformat(&pcm_u8_format);
156
    register_avformat(&pcm_mulaw_format);
157
    register_avformat(&pcm_alaw_format);
158
    register_avformat(&rawvideo_format);
159
#ifndef CONFIG_WIN32
160
    register_avformat(&ffm_format);
161
#endif
162
    register_avformat(&pgm_format);
163
    register_avformat(&ppm_format);
164
    register_avformat(&pgmyuv_format);
165
    register_avformat(&imgyuv_format);
166
    register_avformat(&pgmpipe_format);
167
    register_avformat(&pgmyuvpipe_format);
168
    register_avformat(&ppmpipe_format);
169
#ifdef CONFIG_GRAB
170
    register_avformat(&video_grab_device_format);
171
    register_avformat(&audio_device_format);
172
#endif
173

    
174
    /* file protocols */
175
    register_protocol(&file_protocol);
176
    register_protocol(&pipe_protocol);
177
#ifndef CONFIG_WIN32
178
    register_protocol(&udp_protocol);
179
    register_protocol(&http_protocol);
180
#endif
181
}
182

    
183
/* memory handling */
184

    
185
int av_new_packet(AVPacket *pkt, int size)
186
{
187
    pkt->data = malloc(size);
188
    if (!pkt->data)
189
        return -ENOMEM;
190
    pkt->size = size;
191
    /* sane state */
192
    pkt->pts = 0;
193
    pkt->stream_index = 0;
194
    pkt->flags = 0;
195
    return 0;
196
}
197

    
198
void av_free_packet(AVPacket *pkt)
199
{
200
    free(pkt->data);
201
    /* fail safe */
202
    pkt->data = NULL;
203
    pkt->size = 0;
204
}
205

    
206
/* fifo handling */
207

    
208
int fifo_init(FifoBuffer *f, int size)
209
{
210
    f->buffer = malloc(size);
211
    if (!f->buffer)
212
        return -1;
213
    f->end = f->buffer + size;
214
    f->wptr = f->rptr = f->buffer;
215
    return 0;
216
}
217

    
218
void fifo_free(FifoBuffer *f)
219
{
220
    free(f->buffer);
221
}
222

    
223
int fifo_size(FifoBuffer *f, UINT8 *rptr)
224
{
225
    int size;
226

    
227
    if (f->wptr >= rptr) {
228
        size = f->wptr - rptr;
229
    } else {
230
        size = (f->end - rptr) + (f->wptr - f->buffer);
231
    }
232
    return size;
233
}
234

    
235
/* get data from the fifo (return -1 if not enough data) */
236
int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr)
237
{
238
    UINT8 *rptr = *rptr_ptr;
239
    int size, len;
240

    
241
    if (f->wptr >= rptr) {
242
        size = f->wptr - rptr;
243
    } else {
244
        size = (f->end - rptr) + (f->wptr - f->buffer);
245
    }
246
    
247
    if (size < buf_size)
248
        return -1;
249
    while (buf_size > 0) {
250
        len = f->end - rptr;
251
        if (len > buf_size)
252
            len = buf_size;
253
        memcpy(buf, rptr, len);
254
        buf += len;
255
        rptr += len;
256
        if (rptr >= f->end)
257
            rptr = f->buffer;
258
        buf_size -= len;
259
    }
260
    *rptr_ptr = rptr;
261
    return 0;
262
}
263

    
264
void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr)
265
{
266
    int len;
267
    UINT8 *wptr;
268
    wptr = *wptr_ptr;
269
    while (size > 0) {
270
        len = f->end - wptr;
271
        if (len > size)
272
            len = size;
273
        memcpy(wptr, buf, len);
274
        wptr += len;
275
        if (wptr >= f->end)
276
            wptr = f->buffer;
277
        buf += len;
278
        size -= len;
279
    }
280
    *wptr_ptr = wptr;
281
}
282

    
283
/* media file handling. 
284
   'filename' is the filename to open.
285
   'format_name' is used to force the file format (NULL if auto guess).
286
   'buf_size' is the optional buffer size (zero if default is OK).
287
   'ap' are additionnal parameters needed when opening the file (NULL if default).
288
*/
289

    
290
AVFormatContext *av_open_input_file(const char *filename, 
291
                                    const char *format_name,
292
                                    int buf_size,
293
                                    AVFormatParameters *ap)
294
{
295
    AVFormat *fmt;
296
    AVFormatContext *ic = NULL;
297
    int err;
298

    
299
    ic = av_mallocz(sizeof(AVFormatContext));
300
    if (!ic)
301
        goto fail;
302

    
303
    /* find format */
304
    if (format_name != NULL) {
305
        fmt = guess_format(format_name, NULL, NULL);
306
    } else {
307
        fmt = guess_format(NULL, filename, NULL);
308
    }
309
    if (!fmt || !fmt->read_header) {
310
        return NULL;
311
    }
312
    ic->format = fmt;
313

    
314
    /* if no file needed do not try to open one */
315
    if (!(fmt->flags & AVFMT_NOFILE)) {
316
        if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0)
317
            goto fail;
318
        if (buf_size > 0) {
319
            url_setbufsize(&ic->pb, buf_size);
320
        }
321
    }
322
    
323
    err = ic->format->read_header(ic, ap);
324
    if (err < 0) {
325
        if (!(fmt->flags & AVFMT_NOFILE)) {
326
            url_fclose(&ic->pb);
327
        }
328
        goto fail;
329
    }
330
    
331
    return ic;
332

    
333
 fail:
334
    if (ic)
335
        free(ic);
336
    return NULL;
337
}
338

    
339
int av_read_packet(AVFormatContext *s, AVPacket *pkt)
340
{
341
    AVPacketList *pktl;
342

    
343
    pktl = s->packet_buffer;
344
    if (pktl) {
345
        /* read packet from packet buffer, if there is data */
346
        *pkt = pktl->pkt;
347
        s->packet_buffer = pktl->next;
348
        free(pktl);
349
        return 0;
350
    } else {
351
        return s->format->read_packet(s, pkt);
352
    }
353
}
354

    
355
void av_close_input_file(AVFormatContext *s)
356
{
357
    int i;
358

    
359
    if (s->format->read_close)
360
        s->format->read_close(s);
361
    for(i=0;i<s->nb_streams;i++) {
362
        free(s->streams[i]);
363
    }
364
    if (s->packet_buffer) {
365
        AVPacketList *p, *p1;
366
        p = s->packet_buffer;
367
        while (p != NULL) {
368
            p1 = p->next;
369
            av_free_packet(&p->pkt);
370
            free(p);
371
            p = p1;
372
        }
373
        s->packet_buffer = NULL;
374
    }
375
    if (!(s->format->flags & AVFMT_NOFILE)) {
376
        url_fclose(&s->pb);
377
    }
378
    free(s);
379
}
380

    
381

    
382
int av_write_packet(AVFormatContext *s, AVPacket *pkt, int force_pts)
383
{
384
    /* XXX: currently, an emulation because internal API must change */
385
    return s->format->write_packet(s, pkt->stream_index, pkt->data, pkt->size, force_pts);
386
}
387

    
388
/* "user interface" functions */
389

    
390
void dump_format(AVFormatContext *ic,
391
                 int index, 
392
                 const char *url,
393
                 int is_output)
394
{
395
    int i;
396
    char buf[256];
397

    
398
    fprintf(stderr, "%s #%d, %s, %s '%s':\n", 
399
            is_output ? "Output" : "Input",
400
            index, ic->format->name, 
401
            is_output ? "to" : "from", url);
402
    for(i=0;i<ic->nb_streams;i++) {
403
        AVStream *st = ic->streams[i];
404
        avcodec_string(buf, sizeof(buf), &st->codec, is_output);
405
        fprintf(stderr, "  Stream #%d.%d: %s\n", index, i, buf);
406
    }
407
}
408

    
409
typedef struct {
410
    const char *str;
411
    int width, height;
412
} SizeEntry;
413

    
414
static SizeEntry sizes[] = {
415
    { "sqcif", 128, 96 },
416
    { "qcif", 176, 144 },
417
    { "cif", 352, 288 },
418
    { "4cif", 704, 576 },
419
};
420
    
421
int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
422
{
423
    int i;
424
    int n = sizeof(sizes) / sizeof(SizeEntry);
425
    const char *p;
426
    int frame_width = 0, frame_height = 0;
427

    
428
    for(i=0;i<n;i++) {
429
        if (!strcmp(sizes[i].str, str)) {
430
            frame_width = sizes[i].width;
431
            frame_height = sizes[i].height;
432
            break;
433
        }
434
    }
435
    if (i == n) {
436
        p = str;
437
        frame_width = strtol(p, (char **)&p, 10);
438
        if (*p)
439
            p++;
440
        frame_height = strtol(p, (char **)&p, 10);
441
    }
442
    if (frame_width <= 0 || frame_height <= 0)
443
        return -1;
444
    *width_ptr = frame_width;
445
    *height_ptr = frame_height;
446
    return 0;
447
}
448

    
449
INT64 gettime(void)
450
{
451
#ifdef CONFIG_WIN32
452
    struct _timeb tb;
453
    _ftime(&tb);
454
    return ((INT64)tb.time * INT64_C(1000) + (INT64)tb.millitm) * INT64_C(1000);
455
#else
456
    struct timeval tv;
457
    gettimeofday(&tv,NULL);
458
    return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
459
#endif
460
}
461

    
462
/* syntax: [YYYY-MM-DD ][[HH:]MM:]SS[.m...] . Return the date in micro seconds since 1970 */
463
INT64 parse_date(const char *datestr, int duration)
464
{
465
    const char *p;
466
    INT64 t;
467
    int sec;
468

    
469
    p = datestr;
470
    if (!duration) {
471
        static const UINT8 months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
472
        int year, month, day, i;
473

    
474
        if (strlen(p) >= 5 && p[4] == '-') {
475
            
476
            year = strtol(p, (char **)&p, 10);
477
            if (*p)
478
                p++;
479
            month = strtol(p, (char **)&p, 10) - 1;
480
            if (*p)
481
                p++;
482
            day = strtol(p, (char **)&p, 10) - 1;
483
            if (*p)
484
                p++;
485
            day += (year - 1970) * 365;
486
            /* if >= March, take February of current year into account too */
487
            if (month >= 2)
488
                year++;
489
            for(i=1970;i<year;i++) {
490
                if ((i % 100) == 0) {
491
                    if ((i % 400) == 0) day++;
492
                } else if ((i % 4) == 0) {
493
                    day++;
494
                }
495
            }
496
            for(i=0;i<month;i++)
497
                day += months[i];
498
        } else {
499
            day = (time(NULL) / (3600 * 24));
500
        }
501
        t = day * (3600 * 24);
502
    } else {
503
        t = 0;
504
    }
505
    
506
    sec = 0;
507
    for(;;) {
508
        int val;
509
        val = strtol(p, (char **)&p, 10);
510
        sec = sec * 60 + val;
511
        if (*p != ':')
512
            break;
513
        p++;
514
    }
515
    t = (t + sec) * 1000000;
516
    if (*p == '.') {
517
        int val, n;
518
        p++;
519
        n = strlen(p);
520
        if (n > 6)
521
            n = 6;
522
        val = strtol(p, NULL, 10);
523
        while (n < 6) {
524
            val = val * 10;
525
            n++;
526
        }
527
        t += val;
528
    }
529
    return t;
530
}
531

    
532
/* syntax: '?tag1=val1&tag2=val2...'. No URL decoding is done. Return
533
   1 if found */
534
int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
535
{
536
    const char *p;
537
    char tag[128], *q;
538

    
539
    p = info;
540
    if (*p == '?')
541
        p++;
542
    for(;;) {
543
        q = tag;
544
        while (*p != '\0' && *p != '=' && *p != '&') {
545
            if ((q - tag) < sizeof(tag) - 1)
546
                *q++ = *p;
547
            p++;
548
        }
549
        *q = '\0';
550
        q = arg;
551
        if (*p == '=') {
552
            p++;
553
            while (*p != '&' && *p != '\0') {
554
                if ((q - arg) < arg_size - 1)
555
                    *q++ = *p;
556
                p++;
557
            }
558
            *q = '\0';
559
        }
560
        if (!strcmp(tag, tag1)) 
561
            return 1;
562
        if (*p != '&')
563
            break;
564
    }
565
    return 0;
566
}
567

    
568
/* Return in 'buf' the path with '%d' replaced by number. Also handles
569
   the '%0nd' format where 'n' is the total number of digits and
570
   '%%'. Return 0 if OK, and -1 if format error */
571
int get_frame_filename(char *buf, int buf_size,
572
                       const char *path, int number)
573
{
574
    const char *p;
575
    char *q, buf1[20];
576
    int nd, len, c, percentd_found;
577

    
578
    q = buf;
579
    p = path;
580
    percentd_found = 0;
581
    for(;;) {
582
        c = *p++;
583
        if (c == '\0')
584
            break;
585
        if (c == '%') {
586
            nd = 0;
587
            while (*p >= '0' && *p <= '9') {
588
                nd = nd * 10 + *p++ - '0';
589
            }
590
            c = *p++;
591
            switch(c) {
592
            case '%':
593
                goto addchar;
594
            case 'd':
595
                if (percentd_found)
596
                    goto fail;
597
                percentd_found = 1;
598
                snprintf(buf1, sizeof(buf1), "%0*d", nd, number);
599
                len = strlen(buf1);
600
                if ((q - buf + len) > buf_size - 1)
601
                    goto fail;
602
                memcpy(q, buf1, len);
603
                q += len;
604
                break;
605
            default:
606
                goto fail;
607
            }
608
        } else {
609
        addchar:
610
            if ((q - buf) < buf_size - 1)
611
                *q++ = c;
612
        }
613
    }
614
    if (!percentd_found)
615
        goto fail;
616
    *q = '\0';
617
    return 0;
618
 fail:
619
    *q = '\0';
620
    return -1;
621
}
622

    
623
static int gcd(INT64 a, INT64 b)
624
{
625
    INT64 c;
626

    
627
    while (1) {
628
        c = a % b;
629
        if (c == 0)
630
            return b;
631
        a = b;
632
        b = c;
633
    }
634
}
635

    
636
void ticker_init(Ticker *tick, INT64 inrate, INT64 outrate)
637
{
638
    int g;
639

    
640
    g = gcd(inrate, outrate);
641
    inrate /= g;
642
    outrate /= g;
643

    
644
    tick->value = -outrate/2;
645

    
646
    tick->inrate = inrate;
647
    tick->outrate = outrate;
648
    tick->div = tick->outrate / tick->inrate;
649
    tick->mod = tick->outrate % tick->inrate;
650
}