Statistics
| Branch: | Revision:

ffmpeg / libav / img.c @ 6775c758

History | View | Annotate | Download (15.6 KB)

1
/*
2
 * Image format
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 <unistd.h>
22
#include <fcntl.h>
23
#include <errno.h>
24
#include <string.h>
25
#include <math.h>
26

    
27
#include "avformat.h"
28

    
29
#define IMGFMT_YUV     1
30
#define IMGFMT_PGMYUV  2
31
#define IMGFMT_PGM     3
32
#define IMGFMT_PPM     4
33

    
34
typedef struct {
35
    int width;
36
    int height;
37
    int img_number;
38
    int img_size;
39
    int img_fmt;
40
    int is_pipe;
41
    char path[1024];
42
} VideoData;
43

    
44
static inline int pnm_space(int c)  
45
{
46
    return (c==' ' || c=='\n' || c=='\r' || c=='\t');
47
}
48

    
49
static void pnm_get(ByteIOContext *f, char *str, int buf_size) 
50
{
51
    char *s;
52
    int c;
53
    
54
    do  {
55
        c=get_byte(f);
56
        if (c=='#')  {
57
            do  {
58
                c=get_byte(f);
59
            } while (c!='\n');
60
            c=get_byte(f);
61
        }
62
    } while (pnm_space(c));
63
    
64
    s=str;
65
    do  {
66
        if (url_feof(f))
67
            break;
68
        if ((s - str)  < buf_size - 1)
69
            *s++=c;
70
        c=get_byte(f);
71
    } while (!pnm_space(c));
72
    *s = '\0';
73
}
74

    
75
static int pgm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size, int is_yuv)
76
{
77
    int width, height, i;
78
    char buf1[32];
79
    UINT8 *picture[3];
80

    
81
    width = s->width;
82
    height = s->height;
83

    
84
    pnm_get(f, buf1, sizeof(buf1));
85
    if (strcmp(buf1, "P5")) {
86
        return -EIO;
87
    }
88
    pnm_get(f, buf1, sizeof(buf1));
89
    pnm_get(f, buf1, sizeof(buf1));
90
    pnm_get(f, buf1, sizeof(buf1));
91
    
92
    picture[0] = buf;
93
    picture[1] = buf + width * height;
94
    picture[2] = buf + width * height + (width * height / 4);
95
    get_buffer(f, picture[0], width * height);
96
    
97
    height>>=1;
98
    width>>=1;
99
    if (is_yuv) {
100
        for(i=0;i<height;i++) {
101
            get_buffer(f, picture[1] + i * width, width);
102
            get_buffer(f, picture[2] + i * width, width);
103
        }
104
    } else {
105
        for(i=0;i<height;i++) {
106
            memset(picture[1] + i * width, 128, width);
107
            memset(picture[2] + i * width, 128, width);
108
        }
109
    }
110
    return 0;
111
}
112

    
113
static int ppm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size)
114
{
115
    int width, height;
116
    char buf1[32];
117
    UINT8 *picture[3];
118

    
119
    width = s->width;
120
    height = s->height;
121

    
122
    pnm_get(f, buf1, sizeof(buf1));
123
    if (strcmp(buf1, "P6")) {
124
        return -EIO;
125
    }
126
    
127
    pnm_get(f, buf1, sizeof(buf1));
128
    pnm_get(f, buf1, sizeof(buf1));
129
    pnm_get(f, buf1, sizeof(buf1));
130
    
131
    picture[0] = buf;
132
    get_buffer(f, picture[0], width * height*3);
133
    
134
    return 0;
135

    
136
}
137

    
138
static int yuv_read(VideoData *s, const char *filename, UINT8 *buf, int size1)
139
{
140
    ByteIOContext pb1, *pb = &pb1;
141
    char fname[1024], *p;
142
    int size;
143

    
144
    size = s->width * s->height;
145
    
146
    strcpy(fname, filename);
147
    p = strrchr(fname, '.');
148
    if (!p || p[1] != 'Y')
149
        return -EIO;
150

    
151
    if (url_fopen(pb, fname, URL_RDONLY) < 0)
152
        return -EIO;
153
    
154
    get_buffer(pb, buf, size);
155
    url_fclose(pb);
156
    
157
    p[1] = 'U';
158
    if (url_fopen(pb, fname, URL_RDONLY) < 0)
159
        return -EIO;
160

    
161
    get_buffer(pb, buf + size, size / 4);
162
    url_fclose(pb);
163
    
164
    p[1] = 'V';
165
    if (url_fopen(pb, fname, URL_RDONLY) < 0)
166
        return -EIO;
167

    
168
    get_buffer(pb, buf + size + (size / 4), size / 4);
169
    url_fclose(pb);
170
    return 0;
171
}
172

    
173
int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
174
{
175
    VideoData *s = s1->priv_data;
176
    char filename[1024];
177
    int ret;
178
    ByteIOContext f1, *f;
179

    
180
    snprintf(filename, sizeof(filename), s->path, s->img_number);
181
    
182
    if (!s->is_pipe) {
183
        f = &f1;
184
        if (url_fopen(f, filename, URL_RDONLY) < 0)
185
            return -EIO;
186
    } else {
187
        f = &s1->pb;
188
        if (url_feof(f))
189
            return -EIO;
190
    }
191

    
192
    av_new_packet(pkt, s->img_size);
193
    pkt->stream_index = 0;
194

    
195
    switch(s->img_fmt) {
196
    case IMGFMT_PGMYUV:
197
        ret = pgm_read(s, f, pkt->data, pkt->size, 1);
198
        break;
199
    case IMGFMT_PGM:
200
        ret = pgm_read(s, f, pkt->data, pkt->size, 0);
201
        break;
202
    case IMGFMT_YUV:
203
        ret = yuv_read(s, filename, pkt->data, pkt->size);
204
        break;
205
    case IMGFMT_PPM:
206
        ret = ppm_read(s, f, pkt->data, pkt->size);
207
        break;
208
    default:
209
        return -EIO;
210
    }
211
    
212
    if (!s->is_pipe) {
213
        url_fclose(f);
214
    }
215

    
216
    if (ret < 0) {
217
        av_free_packet(pkt);
218
        return -EIO; /* signal EOF */
219
    } else {
220
        s->img_number++;
221
        return 0;
222
    }
223
}
224

    
225
static int sizes[][2] = {
226
    { 640, 480 },
227
    { 720, 480 },
228
    { 720, 576 },
229
    { 352, 288 },
230
    { 352, 240 },
231
    { 160, 128 },
232
    { 512, 384 },
233
    { 640, 352 },
234
};
235

    
236
static int infer_size(int *width_ptr, int *height_ptr, int size)
237
{
238
    int i;
239

    
240
    for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
241
        if ((sizes[i][0] * sizes[i][1]) == size) {
242
            *width_ptr = sizes[i][0];
243
            *height_ptr = sizes[i][1];
244
            return 0;
245
        }
246
    }
247
    return -1;
248
}
249

    
250
static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
251
{
252
    VideoData *s;
253
    int i, h;
254
    char buf[1024];
255
    char buf1[32];
256
    ByteIOContext pb1, *f = &pb1;
257
    AVStream *st;
258

    
259
    s = malloc(sizeof(VideoData));
260
    if (!s)
261
        return -ENOMEM;
262

    
263
    s1->priv_data = s;
264

    
265
    s1->nb_streams = 1;
266
    st = av_mallocz(sizeof(AVStream));
267
    if (!st) {
268
        free(s);
269
        return -ENOMEM;
270
    }
271
    s1->streams[0] = st;
272
    
273
    strcpy(s->path, s1->filename);
274
    s->img_number = 0;
275

    
276
    /* find format */
277
    if (s1->format->flags & AVFMT_NOFILE)
278
        s->is_pipe = 0;
279
    else
280
        s->is_pipe = 1;
281
        
282
    if (s1->format == &pgmyuvpipe_format ||
283
        s1->format == &pgmyuv_format)
284
        s->img_fmt = IMGFMT_PGMYUV;
285
    else if (s1->format == &pgmpipe_format ||
286
             s1->format == &pgm_format)
287
        s->img_fmt = IMGFMT_PGM;
288
    else if (s1->format == &imgyuv_format)
289
        s->img_fmt = IMGFMT_YUV;
290
    else if (s1->format == &ppmpipe_format ||
291
             s1->format == &ppm_format)
292
        s->img_fmt = IMGFMT_PPM;
293
    else
294
        goto fail;
295

    
296
    if (!s->is_pipe) {
297
        /* try to find the first image */
298
        for(i=0;i<5;i++) {
299
            snprintf(buf, sizeof(buf), s->path, s->img_number);
300
            if (url_fopen(f, buf, URL_RDONLY) >= 0)
301
                break;
302
            s->img_number++;
303
        }
304
        if (i == 5)
305
            goto fail;
306
    } else {
307
        f = &s1->pb;
308
    }
309
    
310
    /* find the image size */
311
    /* XXX: use generic file format guessing, as mpeg */
312
    switch(s->img_fmt) {
313
    case IMGFMT_PGM:
314
    case IMGFMT_PGMYUV:
315
    case IMGFMT_PPM:
316
        pnm_get(f, buf1, sizeof(buf1));
317
        pnm_get(f, buf1, sizeof(buf1));
318
        s->width = atoi(buf1);
319
        pnm_get(f, buf1, sizeof(buf1));
320
        h = atoi(buf1);
321
        if (s->img_fmt == IMGFMT_PGMYUV)
322
            h = (h * 2) / 3;
323
        s->height = h;
324
        if (s->width <= 0 ||
325
            s->height <= 0 ||
326
            (s->width % 2) != 0 ||
327
            (s->height % 2) != 0) {
328
            goto fail1;
329
        }
330
        break;
331
    case IMGFMT_YUV:
332
        /* infer size by using the file size. */
333
        {
334
            int img_size;
335
            URLContext *h;
336

    
337
            /* XXX: hack hack */
338
            h = url_fileno(f);
339
            img_size = lseek((int)h->priv_data, 0, SEEK_END);
340
            if (infer_size(&s->width, &s->height, img_size) < 0) {
341
                goto fail1;
342
            }
343
        }
344
        break;
345
    }
346

    
347
    if (!s->is_pipe) {
348
        url_fclose(f);
349
    } else {
350
        url_fseek(f, 0, SEEK_SET);
351
    }
352
    
353

    
354
    st->codec.codec_type = CODEC_TYPE_VIDEO;
355
    st->codec.codec_id = CODEC_ID_RAWVIDEO;
356
    st->codec.width = s->width;
357
    st->codec.height = s->height;
358
    if (s->img_fmt == IMGFMT_PPM) {
359
        st->codec.pix_fmt = PIX_FMT_RGB24;
360
        s->img_size = (s->width * s->height * 3);
361
    } else {
362
        st->codec.pix_fmt = PIX_FMT_YUV420P;
363
        s->img_size = (s->width * s->height * 3) / 2;
364
    }
365
    if (!ap || !ap->frame_rate)
366
        st->codec.frame_rate = 25 * FRAME_RATE_BASE;
367
    else
368
        st->codec.frame_rate = ap->frame_rate;
369
    
370
    return 0;
371
 fail1:
372
    if (!s->is_pipe)
373
        url_fclose(f);
374
 fail:
375
    free(s);
376
    return -EIO;
377
}
378

    
379
static int img_read_close(AVFormatContext *s1)
380
{
381
    VideoData *s = s1->priv_data;
382
    free(s);
383
    return 0;
384
}
385

    
386
/******************************************************/
387
/* image output */
388

    
389
static int pgm_save(AVPicture *picture, int width, int height, ByteIOContext *pb, int is_yuv) 
390
{
391
    int i, h;
392
    char buf[100];
393
    UINT8 *ptr, *ptr1, *ptr2;
394

    
395
    h = height;
396
    if (is_yuv)
397
        h = (height * 3) / 2;
398
    snprintf(buf, sizeof(buf), 
399
             "P5\n%d %d\n%d\n",
400
             width, h, 255);
401
    put_buffer(pb, buf, strlen(buf));
402
    
403
    ptr = picture->data[0];
404
    for(i=0;i<height;i++) {
405
        put_buffer(pb, ptr, width);
406
        ptr += picture->linesize[0];
407
    }
408

    
409
    if (is_yuv) {
410
        height >>= 1;
411
        width >>= 1;
412
        ptr1 = picture->data[1];
413
        ptr2 = picture->data[2];
414
        for(i=0;i<height;i++) {
415
            put_buffer(pb, ptr1, width);
416
            put_buffer(pb, ptr2, width);
417
            ptr1 += picture->linesize[1];
418
            ptr2 += picture->linesize[2];
419
        }
420
    }
421
    put_flush_packet(pb);
422
    return 0;
423
}
424

    
425
static int ppm_save(AVPicture *picture, int width, int height, ByteIOContext *pb) 
426
{
427
    int i;
428
    char buf[100];
429
    UINT8 *ptr;
430

    
431
    snprintf(buf, sizeof(buf), 
432
             "P6\n%d %d\n%d\n",
433
             width, height, 255);
434
    put_buffer(pb, buf, strlen(buf));
435
    
436
    ptr = picture->data[0];
437
    for(i=0;i<height;i++) {
438
        put_buffer(pb, ptr, width * 3);
439
        ptr += picture->linesize[0];
440
    }
441

    
442
    put_flush_packet(pb);
443
    return 0;
444
}
445

    
446
static int yuv_save(AVPicture *picture, int width, int height, const char *filename)
447
{
448
    ByteIOContext pb1, *pb = &pb1;
449
    char fname[1024], *p;
450
    int i, j;
451
    UINT8 *ptr;
452
    static char *ext = "YUV";
453

    
454
    strcpy(fname, filename);
455
    p = strrchr(fname, '.');
456
    if (!p || p[1] != 'Y')
457
        return -EIO;
458

    
459
    for(i=0;i<3;i++) {
460
        if (i == 1) {
461
            width >>= 1;
462
            height >>= 1;
463
        }
464

    
465
        p[1] = ext[i];
466
        if (url_fopen(pb, fname, URL_WRONLY) < 0)
467
            return -EIO;
468
    
469
        ptr = picture->data[i];
470
        for(j=0;j<height;j++) {
471
            put_buffer(pb, ptr, width);
472
            ptr += picture->linesize[i];
473
        }
474
        put_flush_packet(pb);
475
        url_fclose(pb);
476
    }
477
    return 0;
478
}
479

    
480
static int img_write_header(AVFormatContext *s)
481
{
482
    VideoData *img;
483

    
484
    img = av_mallocz(sizeof(VideoData));
485
    if (!img)
486
        return -1;
487
    s->priv_data = img;
488
    img->img_number = 1;
489
    strcpy(img->path, s->filename);
490

    
491
    /* find format */
492
    if (s->format->flags & AVFMT_NOFILE)
493
        img->is_pipe = 0;
494
    else
495
        img->is_pipe = 1;
496
        
497
    if (s->format == &pgmyuvpipe_format ||
498
        s->format == &pgmyuv_format) {
499
        img->img_fmt = IMGFMT_PGMYUV;
500
    } else if (s->format == &pgmpipe_format ||
501
               s->format == &pgm_format) {
502
        img->img_fmt = IMGFMT_PGM;
503
    } else if (s->format == &imgyuv_format) {
504
        img->img_fmt = IMGFMT_YUV;
505
    } else if (s->format == &ppmpipe_format ||
506
               s->format == &ppm_format) {
507
        img->img_fmt = IMGFMT_PPM;
508
    } else {
509
        goto fail;
510
    }
511
    return 0;
512
 fail:
513
    free(img);
514
    return -EIO;
515
}
516

    
517
static int img_write_packet(AVFormatContext *s, int stream_index,
518
                            UINT8 *buf, int size)
519
{
520
    VideoData *img = s->priv_data;
521
    AVStream *st = s->streams[stream_index];
522
    ByteIOContext pb1, *pb;
523
    AVPicture picture;
524
    int width, height, ret, size1;
525
    char filename[1024];
526

    
527
    width = st->codec.width;
528
    height = st->codec.height;
529

    
530
    switch(st->codec.pix_fmt) {
531
    case PIX_FMT_YUV420P:
532
        size1 = (width * height * 3) / 2;
533
        if (size != size1)
534
            return -EIO;
535
        
536
        picture.data[0] = buf;
537
        picture.data[1] = picture.data[0] + width * height;
538
        picture.data[2] = picture.data[1] + (width * height) / 4;
539
        picture.linesize[0] = width;
540
        picture.linesize[1] = width >> 1; 
541
        picture.linesize[2] = width >> 1;
542
        break;
543
    case PIX_FMT_RGB24:
544
        size1 = (width * height * 3);
545
        if (size != size1)
546
            return -EIO;
547
        picture.data[0] = buf;
548
        picture.linesize[0] = width * 3;
549
        break;
550
    default:
551
        return -EIO;
552
    }
553
    
554
    snprintf(filename, sizeof(filename), img->path, img->img_number);
555

    
556
    if (!img->is_pipe) {
557
        pb = &pb1;
558
        if (url_fopen(pb, filename, URL_WRONLY) < 0)
559
            return -EIO;
560
    } else {
561
        pb = &s->pb;
562
    }
563
    switch(img->img_fmt) {
564
    case IMGFMT_PGMYUV:
565
        ret = pgm_save(&picture, width, height, pb, 1);
566
        break;
567
    case IMGFMT_PGM:
568
        ret = pgm_save(&picture, width, height, pb, 0);
569
        break;
570
    case IMGFMT_YUV:
571
        ret = yuv_save(&picture, width, height, filename);
572
        break;
573
    case IMGFMT_PPM:
574
        ret = ppm_save(&picture, width, height, pb);
575
        break;
576
    }
577
    if (!img->is_pipe) {
578
        url_fclose(pb);
579
    }
580

    
581
    img->img_number++;
582
    return 0;
583
}
584

    
585
static int img_write_trailer(AVFormatContext *s)
586
{
587
    VideoData *img = s->priv_data;
588
    free(img);
589
    return 0;
590
}
591

    
592
AVFormat pgm_format = {
593
    "pgm",
594
    "pgm image format",
595
    "",
596
    "pgm",
597
    CODEC_ID_NONE,
598
    CODEC_ID_RAWVIDEO,
599
    img_write_header,
600
    img_write_packet,
601
    img_write_trailer,
602

    
603
    img_read_header,
604
    img_read_packet,
605
    img_read_close,
606
    NULL,
607
    AVFMT_NOFILE,
608
};
609

    
610
AVFormat pgmyuv_format = {
611
    "pgmyuv",
612
    "pgm with YUV content image format",
613
    "",
614
    "pgm",
615
    CODEC_ID_NONE,
616
    CODEC_ID_RAWVIDEO,
617
    img_write_header,
618
    img_write_packet,
619
    img_write_trailer,
620

    
621
    img_read_header,
622
    img_read_packet,
623
    img_read_close,
624
    NULL,
625
    AVFMT_NOFILE,
626
};
627

    
628
AVFormat ppm_format = {
629
    "ppm",
630
    "ppm image format",
631
    "",
632
    "ppm",
633
    CODEC_ID_NONE,
634
    CODEC_ID_RAWVIDEO,
635
    img_write_header,
636
    img_write_packet,
637
    img_write_trailer,
638

    
639
    img_read_header,
640
    img_read_packet,
641
    img_read_close,
642
    NULL,
643
    AVFMT_NOFILE,
644
};
645

    
646
AVFormat imgyuv_format = {
647
    ".Y.U.V",
648
    ".Y.U.V format",
649
    "",
650
    "Y",
651
    CODEC_ID_NONE,
652
    CODEC_ID_RAWVIDEO,
653
    img_write_header,
654
    img_write_packet,
655
    img_write_trailer,
656

    
657
    img_read_header,
658
    img_read_packet,
659
    img_read_close,
660
    NULL,
661
    AVFMT_NOFILE,
662
};
663

    
664
AVFormat pgmpipe_format = {
665
    "pgmpipe",
666
    "PGM pipe format",
667
    "",
668
    "pgm",
669
    CODEC_ID_NONE,
670
    CODEC_ID_RAWVIDEO,
671
    img_write_header,
672
    img_write_packet,
673
    img_write_trailer,
674

    
675
    img_read_header,
676
    img_read_packet,
677
    img_read_close,
678
    NULL,
679
};
680

    
681
AVFormat pgmyuvpipe_format = {
682
    "pgmyuvpipe",
683
    "PGM YUV pipe format",
684
    "",
685
    "pgm",
686
    CODEC_ID_NONE,
687
    CODEC_ID_RAWVIDEO,
688
    img_write_header,
689
    img_write_packet,
690
    img_write_trailer,
691

    
692
    img_read_header,
693
    img_read_packet,
694
    img_read_close,
695
    NULL,
696
};
697

    
698
AVFormat ppmpipe_format = {
699
    "ppmpipe",
700
    "PPM pipe format",
701
    "",
702
    "ppm",
703
    CODEC_ID_NONE,
704
    CODEC_ID_RAWVIDEO,
705
    img_write_header,
706
    img_write_packet,
707
    img_write_trailer,
708

    
709
    img_read_header,
710
    img_read_packet,
711
    img_read_close,
712
    NULL,
713
};