Statistics
| Branch: | Revision:

ffmpeg / libav / img.c @ 9150f42e

History | View | Annotate | Download (15.7 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 "avformat.h"
20

    
21
#define IMGFMT_YUV     1
22
#define IMGFMT_PGMYUV  2
23
#define IMGFMT_PGM     3
24
#define IMGFMT_PPM     4
25

    
26
typedef struct {
27
    int width;
28
    int height;
29
    int img_number;
30
    int img_size;
31
    int img_fmt;
32
    int is_pipe;
33
    char path[1024];
34
} VideoData;
35

    
36
static inline int pnm_space(int c)  
37
{
38
    return (c==' ' || c=='\n' || c=='\r' || c=='\t');
39
}
40

    
41
static void pnm_get(ByteIOContext *f, char *str, int buf_size) 
42
{
43
    char *s;
44
    int c;
45
    
46
    do  {
47
        c=get_byte(f);
48
        if (c=='#')  {
49
            do  {
50
                c=get_byte(f);
51
            } while (c!='\n');
52
            c=get_byte(f);
53
        }
54
    } while (pnm_space(c));
55
    
56
    s=str;
57
    do  {
58
        if (url_feof(f))
59
            break;
60
        if ((s - str)  < buf_size - 1)
61
            *s++=c;
62
        c=get_byte(f);
63
    } while (!pnm_space(c));
64
    *s = '\0';
65
}
66

    
67
static int pgm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size, int is_yuv)
68
{
69
    int width, height, i;
70
    char buf1[32];
71
    UINT8 *picture[3];
72

    
73
    width = s->width;
74
    height = s->height;
75

    
76
    pnm_get(f, buf1, sizeof(buf1));
77
    if (strcmp(buf1, "P5")) {
78
        return -EIO;
79
    }
80
    pnm_get(f, buf1, sizeof(buf1));
81
    pnm_get(f, buf1, sizeof(buf1));
82
    pnm_get(f, buf1, sizeof(buf1));
83
    
84
    picture[0] = buf;
85
    picture[1] = buf + width * height;
86
    picture[2] = buf + width * height + (width * height / 4);
87
    get_buffer(f, picture[0], width * height);
88
    
89
    height>>=1;
90
    width>>=1;
91
    if (is_yuv) {
92
        for(i=0;i<height;i++) {
93
            get_buffer(f, picture[1] + i * width, width);
94
            get_buffer(f, picture[2] + i * width, width);
95
        }
96
    } else {
97
        for(i=0;i<height;i++) {
98
            memset(picture[1] + i * width, 128, width);
99
            memset(picture[2] + i * width, 128, width);
100
        }
101
    }
102
    return 0;
103
}
104

    
105
static int ppm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size)
106
{
107
    int width, height;
108
    char buf1[32];
109
    UINT8 *picture[3];
110

    
111
    width = s->width;
112
    height = s->height;
113

    
114
    pnm_get(f, buf1, sizeof(buf1));
115
    if (strcmp(buf1, "P6")) {
116
        return -EIO;
117
    }
118
    
119
    pnm_get(f, buf1, sizeof(buf1));
120
    pnm_get(f, buf1, sizeof(buf1));
121
    pnm_get(f, buf1, sizeof(buf1));
122
    
123
    picture[0] = buf;
124
    get_buffer(f, picture[0], width * height*3);
125
    
126
    return 0;
127

    
128
}
129

    
130
static int yuv_read(VideoData *s, const char *filename, UINT8 *buf, int size1)
131
{
132
    ByteIOContext pb1, *pb = &pb1;
133
    char fname[1024], *p;
134
    int size;
135

    
136
    size = s->width * s->height;
137
    
138
    strcpy(fname, filename);
139
    p = strrchr(fname, '.');
140
    if (!p || p[1] != 'Y')
141
        return -EIO;
142

    
143
    if (url_fopen(pb, fname, URL_RDONLY) < 0)
144
        return -EIO;
145
    
146
    get_buffer(pb, buf, size);
147
    url_fclose(pb);
148
    
149
    p[1] = 'U';
150
    if (url_fopen(pb, fname, URL_RDONLY) < 0)
151
        return -EIO;
152

    
153
    get_buffer(pb, buf + size, size / 4);
154
    url_fclose(pb);
155
    
156
    p[1] = 'V';
157
    if (url_fopen(pb, fname, URL_RDONLY) < 0)
158
        return -EIO;
159

    
160
    get_buffer(pb, buf + size + (size / 4), size / 4);
161
    url_fclose(pb);
162
    return 0;
163
}
164

    
165
static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
166
{
167
    VideoData *s = s1->priv_data;
168
    char filename[1024];
169
    int ret;
170
    ByteIOContext f1, *f;
171

    
172
    if (get_frame_filename(filename, sizeof(filename),
173
                           s->path, s->img_number) < 0)
174
        return -EIO;
175
    
176
    if (!s->is_pipe) {
177
        f = &f1;
178
        if (url_fopen(f, filename, URL_RDONLY) < 0)
179
            return -EIO;
180
    } else {
181
        f = &s1->pb;
182
        if (url_feof(f))
183
            return -EIO;
184
    }
185

    
186
    av_new_packet(pkt, s->img_size);
187
    pkt->stream_index = 0;
188

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

    
210
    if (ret < 0) {
211
        av_free_packet(pkt);
212
        return -EIO; /* signal EOF */
213
    } else {
214
        s->img_number++;
215
        return 0;
216
    }
217
}
218

    
219
static int sizes[][2] = {
220
    { 640, 480 },
221
    { 720, 480 },
222
    { 720, 576 },
223
    { 352, 288 },
224
    { 352, 240 },
225
    { 160, 128 },
226
    { 512, 384 },
227
    { 640, 352 },
228
    { 640, 240 },
229
};
230

    
231
static int infer_size(int *width_ptr, int *height_ptr, int size)
232
{
233
    int i;
234

    
235
    for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
236
        if ((sizes[i][0] * sizes[i][1]) == size) {
237
            *width_ptr = sizes[i][0];
238
            *height_ptr = sizes[i][1];
239
            return 0;
240
        }
241
    }
242
    return -1;
243
}
244

    
245
static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
246
{
247
    VideoData *s;
248
    int i, h;
249
    char buf[1024];
250
    char buf1[32];
251
    ByteIOContext pb1, *f = &pb1;
252
    AVStream *st;
253

    
254
    s = malloc(sizeof(VideoData));
255
    if (!s)
256
        return -ENOMEM;
257

    
258
    s1->priv_data = s;
259

    
260
    s1->nb_streams = 1;
261
    st = av_mallocz(sizeof(AVStream));
262
    if (!st) {
263
        free(s);
264
        return -ENOMEM;
265
    }
266
    s1->streams[0] = st;
267
    
268
    strcpy(s->path, s1->filename);
269
    s->img_number = 0;
270

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

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

    
333
            /* XXX: hack hack */
334
            h = url_fileno(f);
335
            img_size = url_seek(h, 0, SEEK_END);
336
            if (infer_size(&s->width, &s->height, img_size) < 0) {
337
                goto fail1;
338
            }
339
        }
340
        break;
341
    }
342

    
343
    if (!s->is_pipe) {
344
        url_fclose(f);
345
    } else {
346
        url_fseek(f, 0, SEEK_SET);
347
    }
348
    
349

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

    
375
static int img_read_close(AVFormatContext *s1)
376
{
377
    VideoData *s = s1->priv_data;
378
    free(s);
379
    return 0;
380
}
381

    
382
/******************************************************/
383
/* image output */
384

    
385
static int pgm_save(AVPicture *picture, int width, int height, ByteIOContext *pb, int is_yuv) 
386
{
387
    int i, h;
388
    char buf[100];
389
    UINT8 *ptr, *ptr1, *ptr2;
390

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

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

    
421
static int ppm_save(AVPicture *picture, int width, int height, ByteIOContext *pb) 
422
{
423
    int i;
424
    char buf[100];
425
    UINT8 *ptr;
426

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

    
438
    put_flush_packet(pb);
439
    return 0;
440
}
441

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

    
450
    strcpy(fname, filename);
451
    p = strrchr(fname, '.');
452
    if (!p || p[1] != 'Y')
453
        return -EIO;
454

    
455
    for(i=0;i<3;i++) {
456
        if (i == 1) {
457
            width >>= 1;
458
            height >>= 1;
459
        }
460

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

    
476
static int img_write_header(AVFormatContext *s)
477
{
478
    VideoData *img;
479

    
480
    img = av_mallocz(sizeof(VideoData));
481
    if (!img)
482
        return -1;
483
    s->priv_data = img;
484
    img->img_number = 1;
485
    strcpy(img->path, s->filename);
486

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

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

    
523
    width = st->codec.width;
524
    height = st->codec.height;
525

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

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

    
579
    img->img_number++;
580
    return 0;
581
}
582

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

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

    
601
    img_read_header,
602
    img_read_packet,
603
    img_read_close,
604
    NULL,
605
    AVFMT_NOFILE | AVFMT_NEEDNUMBER,
606
};
607

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

    
619
    img_read_header,
620
    img_read_packet,
621
    img_read_close,
622
    NULL,
623
    AVFMT_NOFILE | AVFMT_NEEDNUMBER,
624
};
625

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

    
637
    img_read_header,
638
    img_read_packet,
639
    img_read_close,
640
    NULL,
641
    AVFMT_NOFILE | AVFMT_NEEDNUMBER,
642
};
643

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

    
655
    img_read_header,
656
    img_read_packet,
657
    img_read_close,
658
    NULL,
659
    AVFMT_NOFILE | AVFMT_NEEDNUMBER,
660
};
661

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

    
673
    img_read_header,
674
    img_read_packet,
675
    img_read_close,
676
    NULL,
677
};
678

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

    
690
    img_read_header,
691
    img_read_packet,
692
    img_read_close,
693
    NULL,
694
};
695

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

    
707
    img_read_header,
708
    img_read_packet,
709
    img_read_close,
710
    NULL,
711
};