~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to ffmpeg/libavcodec/png.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2008-02-25 15:47:12 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080225154712-qvr11ekcea4c9ry8
Tags: 1.1.6-0.1ubuntu1
* Merge from debian-multimedia (LP: #120003), Ubuntu Changes:
 - For ffmpeg-related build-deps, remove cvs from package names.
 - Standards-Version 3.7.3
 - Maintainer Spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * PNG image format
 
3
 * Copyright (c) 2003 Fabrice Bellard.
 
4
 *
 
5
 * This file is part of FFmpeg.
 
6
 *
 
7
 * FFmpeg is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * FFmpeg is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with FFmpeg; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
20
 */
 
21
#include "avcodec.h"
 
22
 
 
23
/* TODO:
 
24
 * - add 2, 4 and 16 bit depth support
 
25
 * - use filters when generating a png (better compression)
 
26
 */
 
27
 
 
28
#include <zlib.h>
 
29
 
 
30
//#define DEBUG
 
31
 
 
32
#define PNG_COLOR_MASK_PALETTE    1
 
33
#define PNG_COLOR_MASK_COLOR      2
 
34
#define PNG_COLOR_MASK_ALPHA      4
 
35
 
 
36
#define PNG_COLOR_TYPE_GRAY 0
 
37
#define PNG_COLOR_TYPE_PALETTE  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
 
38
#define PNG_COLOR_TYPE_RGB        (PNG_COLOR_MASK_COLOR)
 
39
#define PNG_COLOR_TYPE_RGB_ALPHA  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
 
40
#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
 
41
 
 
42
#define PNG_FILTER_VALUE_NONE  0
 
43
#define PNG_FILTER_VALUE_SUB   1
 
44
#define PNG_FILTER_VALUE_UP    2
 
45
#define PNG_FILTER_VALUE_AVG   3
 
46
#define PNG_FILTER_VALUE_PAETH 4
 
47
 
 
48
#define PNG_IHDR      0x0001
 
49
#define PNG_IDAT      0x0002
 
50
#define PNG_ALLIMAGE  0x0004
 
51
#define PNG_PLTE      0x0008
 
52
 
 
53
#define NB_PASSES 7
 
54
 
 
55
#define IOBUF_SIZE 4096
 
56
 
 
57
typedef struct PNGContext {
 
58
    uint8_t *bytestream;
 
59
    uint8_t *bytestream_start;
 
60
    uint8_t *bytestream_end;
 
61
    AVFrame picture;
 
62
 
 
63
    int state;
 
64
    int width, height;
 
65
    int bit_depth;
 
66
    int color_type;
 
67
    int compression_type;
 
68
    int interlace_type;
 
69
    int filter_type;
 
70
    int channels;
 
71
    int bits_per_pixel;
 
72
    int bpp;
 
73
 
 
74
    uint8_t *image_buf;
 
75
    int image_linesize;
 
76
    uint32_t palette[256];
 
77
    uint8_t *crow_buf;
 
78
    uint8_t *last_row;
 
79
    uint8_t *tmp_row;
 
80
    int pass;
 
81
    int crow_size; /* compressed row size (include filter type) */
 
82
    int row_size; /* decompressed row size */
 
83
    int pass_row_size; /* decompress row size of the current pass */
 
84
    int y;
 
85
    z_stream zstream;
 
86
    uint8_t buf[IOBUF_SIZE];
 
87
} PNGContext;
 
88
 
 
89
static unsigned int get32(uint8_t **b){
 
90
    (*b) += 4;
 
91
    return ((*b)[-4]<<24) + ((*b)[-3]<<16) + ((*b)[-2]<<8) + (*b)[-1];
 
92
}
 
93
 
 
94
#ifdef CONFIG_ENCODERS
 
95
static void put32(uint8_t **b, unsigned int v){
 
96
    *(*b)++= v>>24;
 
97
    *(*b)++= v>>16;
 
98
    *(*b)++= v>>8;
 
99
    *(*b)++= v;
 
100
}
 
101
#endif
 
102
 
 
103
static const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
 
104
 
 
105
/* Mask to determine which y pixels are valid in a pass */
 
106
static const uint8_t png_pass_ymask[NB_PASSES] = {
 
107
    0x80, 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55,
 
108
};
 
109
 
 
110
/* Mask to determine which y pixels can be written in a pass */
 
111
static const uint8_t png_pass_dsp_ymask[NB_PASSES] = {
 
112
    0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55,
 
113
};
 
114
 
 
115
/* minimum x value */
 
116
static const uint8_t png_pass_xmin[NB_PASSES] = {
 
117
    0, 4, 0, 2, 0, 1, 0
 
118
};
 
119
 
 
120
/* x shift to get row width */
 
121
static const uint8_t png_pass_xshift[NB_PASSES] = {
 
122
    3, 3, 2, 2, 1, 1, 0
 
123
};
 
124
 
 
125
/* Mask to determine which pixels are valid in a pass */
 
126
static const uint8_t png_pass_mask[NB_PASSES] = {
 
127
    0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff
 
128
};
 
129
 
 
130
/* Mask to determine which pixels to overwrite while displaying */
 
131
static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
 
132
    0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
 
133
};
 
134
#if 0
 
135
static int png_probe(AVProbeData *pd)
 
136
{
 
137
    if (pd->buf_size >= 8 &&
 
138
        memcmp(pd->buf, pngsig, 8) == 0)
 
139
        return AVPROBE_SCORE_MAX;
 
140
    else
 
141
        return 0;
 
142
}
 
143
#endif
 
144
static void *png_zalloc(void *opaque, unsigned int items, unsigned int size)
 
145
{
 
146
    if(items >= UINT_MAX / size)
 
147
        return NULL;
 
148
    return av_malloc(items * size);
 
149
}
 
150
 
 
151
static void png_zfree(void *opaque, void *ptr)
 
152
{
 
153
    av_free(ptr);
 
154
}
 
155
 
 
156
static int png_get_nb_channels(int color_type)
 
157
{
 
158
    int channels;
 
159
    channels = 1;
 
160
    if ((color_type & (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)) ==
 
161
        PNG_COLOR_MASK_COLOR)
 
162
        channels = 3;
 
163
    if (color_type & PNG_COLOR_MASK_ALPHA)
 
164
        channels++;
 
165
    return channels;
 
166
}
 
167
 
 
168
/* compute the row size of an interleaved pass */
 
169
static int png_pass_row_size(int pass, int bits_per_pixel, int width)
 
170
{
 
171
    int shift, xmin, pass_width;
 
172
 
 
173
    xmin = png_pass_xmin[pass];
 
174
    if (width <= xmin)
 
175
        return 0;
 
176
    shift = png_pass_xshift[pass];
 
177
    pass_width = (width - xmin + (1 << shift) - 1) >> shift;
 
178
    return (pass_width * bits_per_pixel + 7) >> 3;
 
179
}
 
180
 
 
181
/* NOTE: we try to construct a good looking image at each pass. width
 
182
   is the original image width. We also do pixel format convertion at
 
183
   this stage */
 
184
static void png_put_interlaced_row(uint8_t *dst, int width,
 
185
                                   int bits_per_pixel, int pass,
 
186
                                   int color_type, const uint8_t *src)
 
187
{
 
188
    int x, mask, dsp_mask, j, src_x, b, bpp;
 
189
    uint8_t *d;
 
190
    const uint8_t *s;
 
191
 
 
192
    mask = png_pass_mask[pass];
 
193
    dsp_mask = png_pass_dsp_mask[pass];
 
194
    switch(bits_per_pixel) {
 
195
    case 1:
 
196
        /* we must intialize the line to zero before writing to it */
 
197
        if (pass == 0)
 
198
            memset(dst, 0, (width + 7) >> 3);
 
199
        src_x = 0;
 
200
        for(x = 0; x < width; x++) {
 
201
            j = (x & 7);
 
202
            if ((dsp_mask << j) & 0x80) {
 
203
                b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1;
 
204
                dst[x >> 3] |= b << (7 - j);
 
205
            }
 
206
            if ((mask << j) & 0x80)
 
207
                src_x++;
 
208
        }
 
209
        break;
 
210
    default:
 
211
        bpp = bits_per_pixel >> 3;
 
212
        d = dst;
 
213
        s = src;
 
214
        if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
 
215
            for(x = 0; x < width; x++) {
 
216
                j = x & 7;
 
217
                if ((dsp_mask << j) & 0x80) {
 
218
                    *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
 
219
                }
 
220
                d += bpp;
 
221
                if ((mask << j) & 0x80)
 
222
                    s += bpp;
 
223
            }
 
224
        } else {
 
225
            for(x = 0; x < width; x++) {
 
226
                j = x & 7;
 
227
                if ((dsp_mask << j) & 0x80) {
 
228
                    memcpy(d, s, bpp);
 
229
                }
 
230
                d += bpp;
 
231
                if ((mask << j) & 0x80)
 
232
                    s += bpp;
 
233
            }
 
234
        }
 
235
        break;
 
236
    }
 
237
}
 
238
 
 
239
#ifdef CONFIG_ENCODERS
 
240
static void png_get_interlaced_row(uint8_t *dst, int row_size,
 
241
                                   int bits_per_pixel, int pass,
 
242
                                   const uint8_t *src, int width)
 
243
{
 
244
    int x, mask, dst_x, j, b, bpp;
 
245
    uint8_t *d;
 
246
    const uint8_t *s;
 
247
 
 
248
    mask = png_pass_mask[pass];
 
249
    switch(bits_per_pixel) {
 
250
    case 1:
 
251
        memset(dst, 0, row_size);
 
252
        dst_x = 0;
 
253
        for(x = 0; x < width; x++) {
 
254
            j = (x & 7);
 
255
            if ((mask << j) & 0x80) {
 
256
                b = (src[x >> 3] >> (7 - j)) & 1;
 
257
                dst[dst_x >> 3] |= b << (7 - (dst_x & 7));
 
258
                dst_x++;
 
259
            }
 
260
        }
 
261
        break;
 
262
    default:
 
263
        bpp = bits_per_pixel >> 3;
 
264
        d = dst;
 
265
        s = src;
 
266
        for(x = 0; x < width; x++) {
 
267
            j = x & 7;
 
268
            if ((mask << j) & 0x80) {
 
269
                memcpy(d, s, bpp);
 
270
                d += bpp;
 
271
            }
 
272
            s += bpp;
 
273
        }
 
274
        break;
 
275
    }
 
276
}
 
277
#endif
 
278
 
 
279
/* XXX: optimize */
 
280
/* NOTE: 'dst' can be equal to 'last' */
 
281
static void png_filter_row(uint8_t *dst, int filter_type,
 
282
                           uint8_t *src, uint8_t *last, int size, int bpp)
 
283
{
 
284
    int i, p;
 
285
 
 
286
    switch(filter_type) {
 
287
    case PNG_FILTER_VALUE_NONE:
 
288
        memcpy(dst, src, size);
 
289
        break;
 
290
    case PNG_FILTER_VALUE_SUB:
 
291
        for(i = 0; i < bpp; i++) {
 
292
            dst[i] = src[i];
 
293
        }
 
294
        for(i = bpp; i < size; i++) {
 
295
            p = dst[i - bpp];
 
296
            dst[i] = p + src[i];
 
297
        }
 
298
        break;
 
299
    case PNG_FILTER_VALUE_UP:
 
300
        for(i = 0; i < size; i++) {
 
301
            p = last[i];
 
302
            dst[i] = p + src[i];
 
303
        }
 
304
        break;
 
305
    case PNG_FILTER_VALUE_AVG:
 
306
        for(i = 0; i < bpp; i++) {
 
307
            p = (last[i] >> 1);
 
308
            dst[i] = p + src[i];
 
309
        }
 
310
        for(i = bpp; i < size; i++) {
 
311
            p = ((dst[i - bpp] + last[i]) >> 1);
 
312
            dst[i] = p + src[i];
 
313
        }
 
314
        break;
 
315
    case PNG_FILTER_VALUE_PAETH:
 
316
        for(i = 0; i < bpp; i++) {
 
317
            p = last[i];
 
318
            dst[i] = p + src[i];
 
319
        }
 
320
        for(i = bpp; i < size; i++) {
 
321
            int a, b, c, pa, pb, pc;
 
322
 
 
323
            a = dst[i - bpp];
 
324
            b = last[i];
 
325
            c = last[i - bpp];
 
326
 
 
327
            p = b - c;
 
328
            pc = a - c;
 
329
 
 
330
            pa = abs(p);
 
331
            pb = abs(pc);
 
332
            pc = abs(p + pc);
 
333
 
 
334
            if (pa <= pb && pa <= pc)
 
335
                p = a;
 
336
            else if (pb <= pc)
 
337
                p = b;
 
338
            else
 
339
                p = c;
 
340
            dst[i] = p + src[i];
 
341
        }
 
342
        break;
 
343
    }
 
344
}
 
345
 
 
346
#ifdef CONFIG_ENCODERS
 
347
static void convert_from_rgb32(uint8_t *dst, const uint8_t *src, int width)
 
348
{
 
349
    uint8_t *d;
 
350
    int j;
 
351
    unsigned int v;
 
352
 
 
353
    d = dst;
 
354
    for(j = 0; j < width; j++) {
 
355
        v = ((const uint32_t *)src)[j];
 
356
        d[0] = v >> 16;
 
357
        d[1] = v >> 8;
 
358
        d[2] = v;
 
359
        d[3] = v >> 24;
 
360
        d += 4;
 
361
    }
 
362
}
 
363
#endif
 
364
 
 
365
#ifdef CONFIG_DECODERS
 
366
static void convert_to_rgb32(uint8_t *dst, const uint8_t *src, int width)
 
367
{
 
368
    int j;
 
369
    unsigned int r, g, b, a;
 
370
 
 
371
    for(j = 0;j < width; j++) {
 
372
        r = src[0];
 
373
        g = src[1];
 
374
        b = src[2];
 
375
        a = src[3];
 
376
        *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
 
377
        dst += 4;
 
378
        src += 4;
 
379
    }
 
380
}
 
381
 
 
382
/* process exactly one decompressed row */
 
383
static void png_handle_row(PNGContext *s)
 
384
{
 
385
    uint8_t *ptr, *last_row;
 
386
    int got_line;
 
387
 
 
388
    if (!s->interlace_type) {
 
389
        ptr = s->image_buf + s->image_linesize * s->y;
 
390
        /* need to swap bytes correctly for RGB_ALPHA */
 
391
        if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
 
392
            png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
 
393
                           s->last_row, s->row_size, s->bpp);
 
394
            memcpy(s->last_row, s->tmp_row, s->row_size);
 
395
            convert_to_rgb32(ptr, s->tmp_row, s->width);
 
396
        } else {
 
397
            /* in normal case, we avoid one copy */
 
398
            if (s->y == 0)
 
399
                last_row = s->last_row;
 
400
            else
 
401
                last_row = ptr - s->image_linesize;
 
402
 
 
403
            png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1,
 
404
                           last_row, s->row_size, s->bpp);
 
405
        }
 
406
        s->y++;
 
407
        if (s->y == s->height) {
 
408
            s->state |= PNG_ALLIMAGE;
 
409
        }
 
410
    } else {
 
411
        got_line = 0;
 
412
        for(;;) {
 
413
            ptr = s->image_buf + s->image_linesize * s->y;
 
414
            if ((png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
 
415
                /* if we already read one row, it is time to stop to
 
416
                   wait for the next one */
 
417
                if (got_line)
 
418
                    break;
 
419
                png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
 
420
                               s->last_row, s->pass_row_size, s->bpp);
 
421
                memcpy(s->last_row, s->tmp_row, s->pass_row_size);
 
422
                got_line = 1;
 
423
            }
 
424
            if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
 
425
                /* NOTE: RGB32 is handled directly in png_put_interlaced_row */
 
426
                png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
 
427
                                       s->color_type, s->last_row);
 
428
            }
 
429
            s->y++;
 
430
            if (s->y == s->height) {
 
431
                for(;;) {
 
432
                    if (s->pass == NB_PASSES - 1) {
 
433
                        s->state |= PNG_ALLIMAGE;
 
434
                        goto the_end;
 
435
                    } else {
 
436
                        s->pass++;
 
437
                        s->y = 0;
 
438
                        s->pass_row_size = png_pass_row_size(s->pass,
 
439
                                                             s->bits_per_pixel,
 
440
                                                             s->width);
 
441
                        s->crow_size = s->pass_row_size + 1;
 
442
                        if (s->pass_row_size != 0)
 
443
                            break;
 
444
                        /* skip pass if empty row */
 
445
                    }
 
446
                }
 
447
            }
 
448
        }
 
449
    the_end: ;
 
450
    }
 
451
}
 
452
 
 
453
static int png_decode_idat(PNGContext *s, int length)
 
454
{
 
455
    int ret;
 
456
    s->zstream.avail_in = length;
 
457
    s->zstream.next_in = s->bytestream;
 
458
    s->bytestream += length;
 
459
 
 
460
    if(s->bytestream > s->bytestream_end)
 
461
        return -1;
 
462
 
 
463
    /* decode one line if possible */
 
464
    while (s->zstream.avail_in > 0) {
 
465
        ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
 
466
        if (ret != Z_OK && ret != Z_STREAM_END) {
 
467
            return -1;
 
468
        }
 
469
        if (s->zstream.avail_out == 0) {
 
470
            if (!(s->state & PNG_ALLIMAGE)) {
 
471
                png_handle_row(s);
 
472
            }
 
473
            s->zstream.avail_out = s->crow_size;
 
474
            s->zstream.next_out = s->crow_buf;
 
475
        }
 
476
    }
 
477
    return 0;
 
478
}
 
479
 
 
480
static int decode_frame(AVCodecContext *avctx,
 
481
                        void *data, int *data_size,
 
482
                        uint8_t *buf, int buf_size)
 
483
{
 
484
    PNGContext * const s = avctx->priv_data;
 
485
    AVFrame *picture = data;
 
486
    AVFrame * const p= (AVFrame*)&s->picture;
 
487
    uint32_t tag, length;
 
488
    int ret, crc;
 
489
 
 
490
    s->bytestream_start=
 
491
    s->bytestream= buf;
 
492
    s->bytestream_end= buf + buf_size;
 
493
 
 
494
    /* check signature */
 
495
    if (memcmp(s->bytestream, pngsig, 8) != 0)
 
496
        return -1;
 
497
    s->bytestream+= 8;
 
498
    s->y=
 
499
    s->state=0;
 
500
//    memset(s, 0, sizeof(PNGContext));
 
501
    /* init the zlib */
 
502
    s->zstream.zalloc = png_zalloc;
 
503
    s->zstream.zfree = png_zfree;
 
504
    s->zstream.opaque = NULL;
 
505
    ret = inflateInit(&s->zstream);
 
506
    if (ret != Z_OK)
 
507
        return -1;
 
508
    for(;;) {
 
509
        int tag32;
 
510
        if (s->bytestream >= s->bytestream_end)
 
511
            goto fail;
 
512
        length = get32(&s->bytestream);
 
513
        if (length > 0x7fffffff)
 
514
            goto fail;
 
515
        tag32 = get32(&s->bytestream);
 
516
        tag = bswap_32(tag32);
 
517
#ifdef DEBUG
 
518
        av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
 
519
               (tag & 0xff),
 
520
               ((tag >> 8) & 0xff),
 
521
               ((tag >> 16) & 0xff),
 
522
               ((tag >> 24) & 0xff), length);
 
523
#endif
 
524
        switch(tag) {
 
525
        case MKTAG('I', 'H', 'D', 'R'):
 
526
            if (length != 13)
 
527
                goto fail;
 
528
            s->width = get32(&s->bytestream);
 
529
            s->height = get32(&s->bytestream);
 
530
            if(avcodec_check_dimensions(avctx, s->width, s->height)){
 
531
                s->width= s->height= 0;
 
532
                goto fail;
 
533
            }
 
534
            s->bit_depth = *s->bytestream++;
 
535
            s->color_type = *s->bytestream++;
 
536
            s->compression_type = *s->bytestream++;
 
537
            s->filter_type = *s->bytestream++;
 
538
            s->interlace_type = *s->bytestream++;
 
539
            crc = get32(&s->bytestream);
 
540
            s->state |= PNG_IHDR;
 
541
#ifdef DEBUG
 
542
            av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d compression_type=%d filter_type=%d interlace_type=%d\n",
 
543
                   s->width, s->height, s->bit_depth, s->color_type,
 
544
                   s->compression_type, s->filter_type, s->interlace_type);
 
545
#endif
 
546
            break;
 
547
        case MKTAG('I', 'D', 'A', 'T'):
 
548
            if (!(s->state & PNG_IHDR))
 
549
                goto fail;
 
550
            if (!(s->state & PNG_IDAT)) {
 
551
                /* init image info */
 
552
                avctx->width = s->width;
 
553
                avctx->height = s->height;
 
554
 
 
555
                s->channels = png_get_nb_channels(s->color_type);
 
556
                s->bits_per_pixel = s->bit_depth * s->channels;
 
557
                s->bpp = (s->bits_per_pixel + 7) >> 3;
 
558
                s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
 
559
 
 
560
                if (s->bit_depth == 8 &&
 
561
                    s->color_type == PNG_COLOR_TYPE_RGB) {
 
562
                    avctx->pix_fmt = PIX_FMT_RGB24;
 
563
                } else if (s->bit_depth == 8 &&
 
564
                           s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
 
565
                    avctx->pix_fmt = PIX_FMT_RGB32;
 
566
                } else if (s->bit_depth == 8 &&
 
567
                           s->color_type == PNG_COLOR_TYPE_GRAY) {
 
568
                    avctx->pix_fmt = PIX_FMT_GRAY8;
 
569
                } else if (s->bit_depth == 16 &&
 
570
                           s->color_type == PNG_COLOR_TYPE_GRAY) {
 
571
                    avctx->pix_fmt = PIX_FMT_GRAY16BE;
 
572
                } else if (s->bit_depth == 1 &&
 
573
                           s->color_type == PNG_COLOR_TYPE_GRAY) {
 
574
                    avctx->pix_fmt = PIX_FMT_MONOBLACK;
 
575
                } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
 
576
                    avctx->pix_fmt = PIX_FMT_PAL8;
 
577
                } else {
 
578
                    goto fail;
 
579
                }
 
580
                if(p->data[0])
 
581
                    avctx->release_buffer(avctx, p);
 
582
 
 
583
                p->reference= 0;
 
584
                if(avctx->get_buffer(avctx, p) < 0){
 
585
                    av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 
586
                    goto fail;
 
587
                }
 
588
                p->pict_type= FF_I_TYPE;
 
589
                p->key_frame= 1;
 
590
                p->interlaced_frame = !!s->interlace_type;
 
591
 
 
592
                /* compute the compressed row size */
 
593
                if (!s->interlace_type) {
 
594
                    s->crow_size = s->row_size + 1;
 
595
                } else {
 
596
                    s->pass = 0;
 
597
                    s->pass_row_size = png_pass_row_size(s->pass,
 
598
                                                         s->bits_per_pixel,
 
599
                                                         s->width);
 
600
                    s->crow_size = s->pass_row_size + 1;
 
601
                }
 
602
#ifdef DEBUG
 
603
                av_log(avctx, AV_LOG_DEBUG, "row_size=%d crow_size =%d\n",
 
604
                       s->row_size, s->crow_size);
 
605
#endif
 
606
                s->image_buf = p->data[0];
 
607
                s->image_linesize = p->linesize[0];
 
608
                /* copy the palette if needed */
 
609
                if (s->color_type == PNG_COLOR_TYPE_PALETTE)
 
610
                    memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
 
611
                /* empty row is used if differencing to the first row */
 
612
                s->last_row = av_mallocz(s->row_size);
 
613
                if (!s->last_row)
 
614
                    goto fail;
 
615
                if (s->interlace_type ||
 
616
                    s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
 
617
                    s->tmp_row = av_malloc(s->row_size);
 
618
                    if (!s->tmp_row)
 
619
                        goto fail;
 
620
                }
 
621
                /* compressed row */
 
622
                s->crow_buf = av_malloc(s->row_size + 1);
 
623
                if (!s->crow_buf)
 
624
                    goto fail;
 
625
                s->zstream.avail_out = s->crow_size;
 
626
                s->zstream.next_out = s->crow_buf;
 
627
            }
 
628
            s->state |= PNG_IDAT;
 
629
            if (png_decode_idat(s, length) < 0)
 
630
                goto fail;
 
631
            /* skip crc */
 
632
            crc = get32(&s->bytestream);
 
633
            break;
 
634
        case MKTAG('P', 'L', 'T', 'E'):
 
635
            {
 
636
                int n, i, r, g, b;
 
637
 
 
638
                if ((length % 3) != 0 || length > 256 * 3)
 
639
                    goto skip_tag;
 
640
                /* read the palette */
 
641
                n = length / 3;
 
642
                for(i=0;i<n;i++) {
 
643
                    r = *s->bytestream++;
 
644
                    g = *s->bytestream++;
 
645
                    b = *s->bytestream++;
 
646
                    s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
 
647
                }
 
648
                for(;i<256;i++) {
 
649
                    s->palette[i] = (0xff << 24);
 
650
                }
 
651
                s->state |= PNG_PLTE;
 
652
                crc = get32(&s->bytestream);
 
653
            }
 
654
            break;
 
655
        case MKTAG('t', 'R', 'N', 'S'):
 
656
            {
 
657
                int v, i;
 
658
 
 
659
                /* read the transparency. XXX: Only palette mode supported */
 
660
                if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
 
661
                    length > 256 ||
 
662
                    !(s->state & PNG_PLTE))
 
663
                    goto skip_tag;
 
664
                for(i=0;i<length;i++) {
 
665
                    v = *s->bytestream++;
 
666
                    s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
 
667
                }
 
668
                crc = get32(&s->bytestream);
 
669
            }
 
670
            break;
 
671
        case MKTAG('I', 'E', 'N', 'D'):
 
672
            if (!(s->state & PNG_ALLIMAGE))
 
673
                goto fail;
 
674
            crc = get32(&s->bytestream);
 
675
            goto exit_loop;
 
676
        default:
 
677
            /* skip tag */
 
678
        skip_tag:
 
679
            s->bytestream += length + 4;
 
680
            break;
 
681
        }
 
682
    }
 
683
 exit_loop:
 
684
    *picture= *(AVFrame*)&s->picture;
 
685
    *data_size = sizeof(AVPicture);
 
686
 
 
687
    ret = s->bytestream - s->bytestream_start;
 
688
 the_end:
 
689
    inflateEnd(&s->zstream);
 
690
    av_freep(&s->crow_buf);
 
691
    av_freep(&s->last_row);
 
692
    av_freep(&s->tmp_row);
 
693
    return ret;
 
694
 fail:
 
695
    ret = -1;
 
696
    goto the_end;
 
697
}
 
698
#endif
 
699
 
 
700
#ifdef CONFIG_ENCODERS
 
701
static void png_write_chunk(uint8_t **f, uint32_t tag,
 
702
                            const uint8_t *buf, int length)
 
703
{
 
704
    uint32_t crc;
 
705
    uint8_t tagbuf[4];
 
706
 
 
707
    put32(f, length);
 
708
    crc = crc32(0, Z_NULL, 0);
 
709
    tagbuf[0] = tag;
 
710
    tagbuf[1] = tag >> 8;
 
711
    tagbuf[2] = tag >> 16;
 
712
    tagbuf[3] = tag >> 24;
 
713
    crc = crc32(crc, tagbuf, 4);
 
714
    put32(f, bswap_32(tag));
 
715
    if (length > 0) {
 
716
        crc = crc32(crc, buf, length);
 
717
        memcpy(*f, buf, length);
 
718
        *f += length;
 
719
    }
 
720
    put32(f, crc);
 
721
}
 
722
 
 
723
/* XXX: use avcodec generic function ? */
 
724
static void to_be32(uint8_t *p, uint32_t v)
 
725
{
 
726
    p[0] = v >> 24;
 
727
    p[1] = v >> 16;
 
728
    p[2] = v >> 8;
 
729
    p[3] = v;
 
730
}
 
731
 
 
732
/* XXX: do filtering */
 
733
static int png_write_row(PNGContext *s, const uint8_t *data, int size)
 
734
{
 
735
    int ret;
 
736
 
 
737
    s->zstream.avail_in = size;
 
738
    s->zstream.next_in = (uint8_t *)data;
 
739
    while (s->zstream.avail_in > 0) {
 
740
        ret = deflate(&s->zstream, Z_NO_FLUSH);
 
741
        if (ret != Z_OK)
 
742
            return -1;
 
743
        if (s->zstream.avail_out == 0) {
 
744
            if(s->bytestream_end - s->bytestream > IOBUF_SIZE + 100)
 
745
                png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, IOBUF_SIZE);
 
746
            s->zstream.avail_out = IOBUF_SIZE;
 
747
            s->zstream.next_out = s->buf;
 
748
        }
 
749
    }
 
750
    return 0;
 
751
}
 
752
#endif /* CONFIG_ENCODERS */
 
753
 
 
754
static int common_init(AVCodecContext *avctx){
 
755
    PNGContext *s = avctx->priv_data;
 
756
 
 
757
    avcodec_get_frame_defaults((AVFrame*)&s->picture);
 
758
    avctx->coded_frame= (AVFrame*)&s->picture;
 
759
//    s->avctx= avctx;
 
760
 
 
761
    return 0;
 
762
}
 
763
 
 
764
#ifdef CONFIG_ENCODERS
 
765
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
 
766
    PNGContext *s = avctx->priv_data;
 
767
    AVFrame *pict = data;
 
768
    AVFrame * const p= (AVFrame*)&s->picture;
 
769
    int bit_depth, color_type, y, len, row_size, ret, is_progressive;
 
770
    int bits_per_pixel, pass_row_size;
 
771
    uint8_t *ptr;
 
772
    uint8_t *crow_buf = NULL;
 
773
    uint8_t *tmp_buf = NULL;
 
774
 
 
775
    *p = *pict;
 
776
    p->pict_type= FF_I_TYPE;
 
777
    p->key_frame= 1;
 
778
 
 
779
    s->bytestream_start=
 
780
    s->bytestream= buf;
 
781
    s->bytestream_end= buf+buf_size;
 
782
 
 
783
    is_progressive = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT);
 
784
    switch(avctx->pix_fmt) {
 
785
    case PIX_FMT_RGB32:
 
786
        bit_depth = 8;
 
787
        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
 
788
        break;
 
789
    case PIX_FMT_RGB24:
 
790
        bit_depth = 8;
 
791
        color_type = PNG_COLOR_TYPE_RGB;
 
792
        break;
 
793
    case PIX_FMT_GRAY8:
 
794
        bit_depth = 8;
 
795
        color_type = PNG_COLOR_TYPE_GRAY;
 
796
        break;
 
797
    case PIX_FMT_MONOBLACK:
 
798
        bit_depth = 1;
 
799
        color_type = PNG_COLOR_TYPE_GRAY;
 
800
        break;
 
801
    case PIX_FMT_PAL8:
 
802
        bit_depth = 8;
 
803
        color_type = PNG_COLOR_TYPE_PALETTE;
 
804
        break;
 
805
    default:
 
806
        return -1;
 
807
    }
 
808
    bits_per_pixel = png_get_nb_channels(color_type) * bit_depth;
 
809
    row_size = (avctx->width * bits_per_pixel + 7) >> 3;
 
810
 
 
811
    s->zstream.zalloc = png_zalloc;
 
812
    s->zstream.zfree = png_zfree;
 
813
    s->zstream.opaque = NULL;
 
814
    ret = deflateInit2(&s->zstream, Z_DEFAULT_COMPRESSION,
 
815
                       Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
 
816
    if (ret != Z_OK)
 
817
        return -1;
 
818
    crow_buf = av_malloc(row_size + 1);
 
819
    if (!crow_buf)
 
820
        goto fail;
 
821
    if (is_progressive) {
 
822
        tmp_buf = av_malloc(row_size + 1);
 
823
        if (!tmp_buf)
 
824
            goto fail;
 
825
    }
 
826
 
 
827
    /* write png header */
 
828
    memcpy(s->bytestream, pngsig, 8);
 
829
    s->bytestream += 8;
 
830
 
 
831
    to_be32(s->buf, avctx->width);
 
832
    to_be32(s->buf + 4, avctx->height);
 
833
    s->buf[8] = bit_depth;
 
834
    s->buf[9] = color_type;
 
835
    s->buf[10] = 0; /* compression type */
 
836
    s->buf[11] = 0; /* filter type */
 
837
    s->buf[12] = is_progressive; /* interlace type */
 
838
 
 
839
    png_write_chunk(&s->bytestream, MKTAG('I', 'H', 'D', 'R'), s->buf, 13);
 
840
 
 
841
    /* put the palette if needed */
 
842
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
 
843
        int has_alpha, alpha, i;
 
844
        unsigned int v;
 
845
        uint32_t *palette;
 
846
        uint8_t *alpha_ptr;
 
847
 
 
848
        palette = (uint32_t *)p->data[1];
 
849
        ptr = s->buf;
 
850
        alpha_ptr = s->buf + 256 * 3;
 
851
        has_alpha = 0;
 
852
        for(i = 0; i < 256; i++) {
 
853
            v = palette[i];
 
854
            alpha = v >> 24;
 
855
            if (alpha && alpha != 0xff)
 
856
                has_alpha = 1;
 
857
            *alpha_ptr++ = alpha;
 
858
            ptr[0] = v >> 16;
 
859
            ptr[1] = v >> 8;
 
860
            ptr[2] = v;
 
861
            ptr += 3;
 
862
        }
 
863
        png_write_chunk(&s->bytestream, MKTAG('P', 'L', 'T', 'E'), s->buf, 256 * 3);
 
864
        if (has_alpha) {
 
865
            png_write_chunk(&s->bytestream, MKTAG('t', 'R', 'N', 'S'), s->buf + 256 * 3, 256);
 
866
        }
 
867
    }
 
868
 
 
869
    /* now put each row */
 
870
    s->zstream.avail_out = IOBUF_SIZE;
 
871
    s->zstream.next_out = s->buf;
 
872
    if (is_progressive) {
 
873
        uint8_t *ptr1;
 
874
        int pass;
 
875
 
 
876
        for(pass = 0; pass < NB_PASSES; pass++) {
 
877
            /* NOTE: a pass is completely omited if no pixels would be
 
878
               output */
 
879
            pass_row_size = png_pass_row_size(pass, bits_per_pixel, avctx->width);
 
880
            if (pass_row_size > 0) {
 
881
                for(y = 0; y < avctx->height; y++) {
 
882
                    if ((png_pass_ymask[pass] << (y & 7)) & 0x80) {
 
883
                        ptr = p->data[0] + y * p->linesize[0];
 
884
                        if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
 
885
                            convert_from_rgb32(tmp_buf, ptr, avctx->width);
 
886
                            ptr1 = tmp_buf;
 
887
                        } else {
 
888
                            ptr1 = ptr;
 
889
                        }
 
890
                        png_get_interlaced_row(crow_buf + 1, pass_row_size,
 
891
                                               bits_per_pixel, pass,
 
892
                                               ptr1, avctx->width);
 
893
                        crow_buf[0] = PNG_FILTER_VALUE_NONE;
 
894
                        png_write_row(s, crow_buf, pass_row_size + 1);
 
895
                    }
 
896
                }
 
897
            }
 
898
        }
 
899
    } else {
 
900
        for(y = 0; y < avctx->height; y++) {
 
901
            ptr = p->data[0] + y * p->linesize[0];
 
902
            if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
 
903
                convert_from_rgb32(crow_buf + 1, ptr, avctx->width);
 
904
            else
 
905
                memcpy(crow_buf + 1, ptr, row_size);
 
906
            crow_buf[0] = PNG_FILTER_VALUE_NONE;
 
907
            png_write_row(s, crow_buf, row_size + 1);
 
908
        }
 
909
    }
 
910
    /* compress last bytes */
 
911
    for(;;) {
 
912
        ret = deflate(&s->zstream, Z_FINISH);
 
913
        if (ret == Z_OK || ret == Z_STREAM_END) {
 
914
            len = IOBUF_SIZE - s->zstream.avail_out;
 
915
            if (len > 0 && s->bytestream_end - s->bytestream > len + 100) {
 
916
                png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, len);
 
917
            }
 
918
            s->zstream.avail_out = IOBUF_SIZE;
 
919
            s->zstream.next_out = s->buf;
 
920
            if (ret == Z_STREAM_END)
 
921
                break;
 
922
        } else {
 
923
            goto fail;
 
924
        }
 
925
    }
 
926
    png_write_chunk(&s->bytestream, MKTAG('I', 'E', 'N', 'D'), NULL, 0);
 
927
 
 
928
    ret = s->bytestream - s->bytestream_start;
 
929
 the_end:
 
930
    av_free(crow_buf);
 
931
    av_free(tmp_buf);
 
932
    deflateEnd(&s->zstream);
 
933
    return ret;
 
934
 fail:
 
935
    ret = -1;
 
936
    goto the_end;
 
937
}
 
938
#endif
 
939
 
 
940
#ifdef CONFIG_PNG_DECODER
 
941
AVCodec png_decoder = {
 
942
    "png",
 
943
    CODEC_TYPE_VIDEO,
 
944
    CODEC_ID_PNG,
 
945
    sizeof(PNGContext),
 
946
    common_init,
 
947
    NULL,
 
948
    NULL, //decode_end,
 
949
    decode_frame,
 
950
    0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
 
951
    NULL
 
952
};
 
953
#endif
 
954
 
 
955
#ifdef CONFIG_PNG_ENCODER
 
956
AVCodec png_encoder = {
 
957
    "png",
 
958
    CODEC_TYPE_VIDEO,
 
959
    CODEC_ID_PNG,
 
960
    sizeof(PNGContext),
 
961
    common_init,
 
962
    encode_frame,
 
963
    NULL, //encode_end,
 
964
    .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_PAL8, PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, -1},
 
965
};
 
966
#endif // CONFIG_PNG_ENCODER