~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): Lionel Le Folgoc, Andrew Starr-Bochicchio, Lionel Le Folgoc
  • Date: 2008-12-26 00:10:06 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20081226001006-2040ls9680bd1blt
Tags: 1.1.7-0.2ubuntu1
[ Andrew Starr-Bochicchio ]
* Merge from debian-multimedia (LP: #298547), Ubuntu Changes:
 - For ffmpeg-related build-deps, fix versionized dependencies
   as the ubuntu versioning is different than debian-multimedia's.

[ Lionel Le Folgoc ]
* LP: #311412 is fixed since the 1.1.7~rc1-0.1 revision.
* debian/patches/03_ffmpeg.diff: updated to fix FTBFS due to libswscale API
  change (cherry-pick from Gentoo #234383).

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
20
 */
21
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};
 
22
#include "bytestream.h"
 
23
#include "png.h"
 
24
 
 
25
const uint8_t ff_pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
 
26
const uint8_t ff_mngsig[8] = {138, 77, 78, 71, 13, 10, 26, 10};
104
27
 
105
28
/* Mask to determine which y pixels are valid in a pass */
106
 
static const uint8_t png_pass_ymask[NB_PASSES] = {
 
29
const uint8_t ff_png_pass_ymask[NB_PASSES] = {
107
30
    0x80, 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55,
108
31
};
109
32
 
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
33
/* minimum x value */
116
 
static const uint8_t png_pass_xmin[NB_PASSES] = {
 
34
const uint8_t ff_png_pass_xmin[NB_PASSES] = {
117
35
    0, 4, 0, 2, 0, 1, 0
118
36
};
119
37
 
120
38
/* x shift to get row width */
121
 
static const uint8_t png_pass_xshift[NB_PASSES] = {
 
39
const uint8_t ff_png_pass_xshift[NB_PASSES] = {
122
40
    3, 3, 2, 2, 1, 1, 0
123
41
};
124
42
 
125
43
/* Mask to determine which pixels are valid in a pass */
126
 
static const uint8_t png_pass_mask[NB_PASSES] = {
 
44
const uint8_t ff_png_pass_mask[NB_PASSES] = {
127
45
    0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff
128
46
};
129
47
 
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)
 
48
void *ff_png_zalloc(void *opaque, unsigned int items, unsigned int size)
145
49
{
146
50
    if(items >= UINT_MAX / size)
147
51
        return NULL;
148
52
    return av_malloc(items * size);
149
53
}
150
54
 
151
 
static void png_zfree(void *opaque, void *ptr)
 
55
void ff_png_zfree(void *opaque, void *ptr)
152
56
{
153
57
    av_free(ptr);
154
58
}
155
59
 
156
 
static int png_get_nb_channels(int color_type)
 
60
int ff_png_get_nb_channels(int color_type)
157
61
{
158
62
    int channels;
159
63
    channels = 1;
166
70
}
167
71
 
168
72
/* compute the row size of an interleaved pass */
169
 
static int png_pass_row_size(int pass, int bits_per_pixel, int width)
 
73
int ff_png_pass_row_size(int pass, int bits_per_pixel, int width)
170
74
{
171
75
    int shift, xmin, pass_width;
172
76
 
173
 
    xmin = png_pass_xmin[pass];
 
77
    xmin = ff_png_pass_xmin[pass];
174
78
    if (width <= xmin)
175
79
        return 0;
176
 
    shift = png_pass_xshift[pass];
 
80
    shift = ff_png_pass_xshift[pass];
177
81
    pass_width = (width - xmin + (1 << shift) - 1) >> shift;
178
82
    return (pass_width * bits_per_pixel + 7) >> 3;
179
83
}
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