static void png_filter_row(DSPContext *dsp, uint8_t *dst, int filter_type,
                           uint8_t *src, uint8_t *last, int size, int bpp)
{
    int i, p, r, g, b, a;
    switch(filter_type) {
    case PNG_FILTER_VALUE_NONE:
        memcpy(dst, src, size);
        break;
    case PNG_FILTER_VALUE_SUB:
        for(i = 0; i < bpp; i++) {
            dst[i] = src[i];
        }
        if(bpp == 4) {
            p = *(int*)dst;
            for(; i < size; i+=bpp) {
                int s = *(int*)(src+i);
                p = ((s&0x7f7f7f7f) + (p&0x7f7f7f7f)) ^ ((s^p)&0x80808080);
                *(int*)(dst+i) = p;
            }
        } else {
#define OP_SUB(x,s,l) x+s
            UNROLL_FILTER(OP_SUB);
        }
        break;
    case PNG_FILTER_VALUE_UP:
        dsp->add_bytes_l2(dst, src, last, size);
        break;
    case PNG_FILTER_VALUE_AVG:
        for(i = 0; i < bpp; i++) {
            p = (last[i] >> 1);
            dst[i] = p + src[i];
        }
#define OP_AVG(x,s,l) (((x + l) >> 1) + s) & 0xff
        UNROLL_FILTER(OP_AVG);
        break;
    case PNG_FILTER_VALUE_PAETH:
        for(i = 0; i < bpp; i++) {
            p = last[i];
            dst[i] = p + src[i];
        }
        if(bpp > 1 && size > 4) {
            int w = bpp==4 ? size : size-3;
            dsp->add_png_paeth_prediction(dst+i, src+i, last+i, w-i, bpp);
            i = w;
        }
        ff_add_png_paeth_prediction(dst+i, src+i, last+i, size-i, bpp);
        break;
    }
}
['static int decode_frame(AVCodecContext *avctx,\n                        void *data, int *data_size,\n                        const uint8_t *buf, int buf_size)\n{\n    PNGDecContext * const s = avctx->priv_data;\n    AVFrame *picture = data;\n    AVFrame * const p= (AVFrame*)&s->picture;\n    uint32_t tag, length;\n    int ret, crc;\n    s->bytestream_start=\n    s->bytestream= buf;\n    s->bytestream_end= buf + buf_size;\n    if (memcmp(s->bytestream, ff_pngsig, 8) != 0 &&\n        memcmp(s->bytestream, ff_mngsig, 8) != 0)\n        return -1;\n    s->bytestream+= 8;\n    s->y=\n    s->state=0;\n    s->zstream.zalloc = ff_png_zalloc;\n    s->zstream.zfree = ff_png_zfree;\n    s->zstream.opaque = NULL;\n    ret = inflateInit(&s->zstream);\n    if (ret != Z_OK)\n        return -1;\n    for(;;) {\n        int tag32;\n        if (s->bytestream >= s->bytestream_end)\n            goto fail;\n        length = bytestream_get_be32(&s->bytestream);\n        if (length > 0x7fffffff)\n            goto fail;\n        tag32 = bytestream_get_be32(&s->bytestream);\n        tag = bswap_32(tag32);\n#ifdef DEBUG\n        av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\\n",\n               (tag & 0xff),\n               ((tag >> 8) & 0xff),\n               ((tag >> 16) & 0xff),\n               ((tag >> 24) & 0xff), length);\n#endif\n        switch(tag) {\n        case MKTAG(\'I\', \'H\', \'D\', \'R\'):\n            if (length != 13)\n                goto fail;\n            s->width = bytestream_get_be32(&s->bytestream);\n            s->height = bytestream_get_be32(&s->bytestream);\n            if(avcodec_check_dimensions(avctx, s->width, s->height)){\n                s->width= s->height= 0;\n                goto fail;\n            }\n            s->bit_depth = *s->bytestream++;\n            s->color_type = *s->bytestream++;\n            s->compression_type = *s->bytestream++;\n            s->filter_type = *s->bytestream++;\n            s->interlace_type = *s->bytestream++;\n            crc = bytestream_get_be32(&s->bytestream);\n            s->state |= PNG_IHDR;\n#ifdef DEBUG\n            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",\n                   s->width, s->height, s->bit_depth, s->color_type,\n                   s->compression_type, s->filter_type, s->interlace_type);\n#endif\n            break;\n        case MKTAG(\'I\', \'D\', \'A\', \'T\'):\n            if (!(s->state & PNG_IHDR))\n                goto fail;\n            if (!(s->state & PNG_IDAT)) {\n                avctx->width = s->width;\n                avctx->height = s->height;\n                s->channels = ff_png_get_nb_channels(s->color_type);\n                s->bits_per_pixel = s->bit_depth * s->channels;\n                s->bpp = (s->bits_per_pixel + 7) >> 3;\n                s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;\n                if (s->bit_depth == 8 &&\n                    s->color_type == PNG_COLOR_TYPE_RGB) {\n                    avctx->pix_fmt = PIX_FMT_RGB24;\n                } else if (s->bit_depth == 8 &&\n                           s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {\n                    avctx->pix_fmt = PIX_FMT_RGB32;\n                } else if (s->bit_depth == 8 &&\n                           s->color_type == PNG_COLOR_TYPE_GRAY) {\n                    avctx->pix_fmt = PIX_FMT_GRAY8;\n                } else if (s->bit_depth == 16 &&\n                           s->color_type == PNG_COLOR_TYPE_GRAY) {\n                    avctx->pix_fmt = PIX_FMT_GRAY16BE;\n                } else if (s->bit_depth == 1 &&\n                           s->color_type == PNG_COLOR_TYPE_GRAY) {\n                    avctx->pix_fmt = PIX_FMT_MONOBLACK;\n                } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {\n                    avctx->pix_fmt = PIX_FMT_PAL8;\n                } else {\n                    goto fail;\n                }\n                if(p->data[0])\n                    avctx->release_buffer(avctx, p);\n                p->reference= 0;\n                if(avctx->get_buffer(avctx, p) < 0){\n                    av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\\n");\n                    goto fail;\n                }\n                p->pict_type= FF_I_TYPE;\n                p->key_frame= 1;\n                p->interlaced_frame = !!s->interlace_type;\n                if (!s->interlace_type) {\n                    s->crow_size = s->row_size + 1;\n                } else {\n                    s->pass = 0;\n                    s->pass_row_size = ff_png_pass_row_size(s->pass,\n                                                         s->bits_per_pixel,\n                                                         s->width);\n                    s->crow_size = s->pass_row_size + 1;\n                }\n#ifdef DEBUG\n                av_log(avctx, AV_LOG_DEBUG, "row_size=%d crow_size =%d\\n",\n                       s->row_size, s->crow_size);\n#endif\n                s->image_buf = p->data[0];\n                s->image_linesize = p->linesize[0];\n                if (s->color_type == PNG_COLOR_TYPE_PALETTE)\n                    memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));\n                s->last_row = av_mallocz(s->row_size);\n                if (!s->last_row)\n                    goto fail;\n                if (s->interlace_type ||\n                    s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {\n                    s->tmp_row = av_malloc(s->row_size);\n                    if (!s->tmp_row)\n                        goto fail;\n                }\n                s->crow_buf = av_malloc(s->row_size + 1);\n                if (!s->crow_buf)\n                    goto fail;\n                s->zstream.avail_out = s->crow_size;\n                s->zstream.next_out = s->crow_buf;\n            }\n            s->state |= PNG_IDAT;\n            if (png_decode_idat(s, length) < 0)\n                goto fail;\n            crc = bytestream_get_be32(&s->bytestream);\n            break;\n        case MKTAG(\'P\', \'L\', \'T\', \'E\'):\n            {\n                int n, i, r, g, b;\n                if ((length % 3) != 0 || length > 256 * 3)\n                    goto skip_tag;\n                n = length / 3;\n                for(i=0;i<n;i++) {\n                    r = *s->bytestream++;\n                    g = *s->bytestream++;\n                    b = *s->bytestream++;\n                    s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;\n                }\n                for(;i<256;i++) {\n                    s->palette[i] = (0xff << 24);\n                }\n                s->state |= PNG_PLTE;\n                crc = bytestream_get_be32(&s->bytestream);\n            }\n            break;\n        case MKTAG(\'t\', \'R\', \'N\', \'S\'):\n            {\n                int v, i;\n                if (s->color_type != PNG_COLOR_TYPE_PALETTE ||\n                    length > 256 ||\n                    !(s->state & PNG_PLTE))\n                    goto skip_tag;\n                for(i=0;i<length;i++) {\n                    v = *s->bytestream++;\n                    s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);\n                }\n                crc = bytestream_get_be32(&s->bytestream);\n            }\n            break;\n        case MKTAG(\'I\', \'E\', \'N\', \'D\'):\n            if (!(s->state & PNG_ALLIMAGE))\n                goto fail;\n            crc = bytestream_get_be32(&s->bytestream);\n            goto exit_loop;\n        default:\n        skip_tag:\n            s->bytestream += length + 4;\n            break;\n        }\n    }\n exit_loop:\n    *picture= *(AVFrame*)&s->picture;\n    *data_size = sizeof(AVPicture);\n    ret = s->bytestream - s->bytestream_start;\n the_end:\n    inflateEnd(&s->zstream);\n    av_freep(&s->crow_buf);\n    av_freep(&s->last_row);\n    av_freep(&s->tmp_row);\n    return ret;\n fail:\n    ret = -1;\n    goto the_end;\n}', 'static int png_decode_idat(PNGDecContext *s, int length)\n{\n    int ret;\n    s->zstream.avail_in = length;\n    s->zstream.next_in = s->bytestream;\n    s->bytestream += length;\n    if(s->bytestream > s->bytestream_end)\n        return -1;\n    while (s->zstream.avail_in > 0) {\n        ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);\n        if (ret != Z_OK && ret != Z_STREAM_END) {\n            return -1;\n        }\n        if (s->zstream.avail_out == 0) {\n            if (!(s->state & PNG_ALLIMAGE)) {\n                png_handle_row(s);\n            }\n            s->zstream.avail_out = s->crow_size;\n            s->zstream.next_out = s->crow_buf;\n        }\n    }\n    return 0;\n}', 'static void png_handle_row(PNGDecContext *s)\n{\n    uint8_t *ptr, *last_row;\n    int got_line;\n    if (!s->interlace_type) {\n        ptr = s->image_buf + s->image_linesize * s->y;\n        if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {\n            png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1,\n                           s->last_row, s->row_size, s->bpp);\n            convert_to_rgb32(ptr, s->tmp_row, s->width, s->filter_type == PNG_FILTER_TYPE_LOCO);\n            FFSWAP(uint8_t*, s->last_row, s->tmp_row);\n        } else {\n            if (s->y == 0)\n                last_row = s->last_row;\n            else\n                last_row = ptr - s->image_linesize;\n            png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1,\n                           last_row, s->row_size, s->bpp);\n        }\n        if (s->filter_type == PNG_FILTER_TYPE_LOCO &&\n            s->color_type == PNG_COLOR_TYPE_RGB && s->y > 0)\n            deloco_rgb24(ptr - s->image_linesize, s->row_size);\n        s->y++;\n        if (s->y == s->height) {\n            s->state |= PNG_ALLIMAGE;\n            if (s->filter_type == PNG_FILTER_TYPE_LOCO &&\n                s->color_type == PNG_COLOR_TYPE_RGB)\n                deloco_rgb24(ptr, s->row_size);\n        }\n    } else {\n        got_line = 0;\n        for(;;) {\n            ptr = s->image_buf + s->image_linesize * s->y;\n            if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {\n                if (got_line)\n                    break;\n                png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1,\n                               s->last_row, s->pass_row_size, s->bpp);\n                FFSWAP(uint8_t*, s->last_row, s->tmp_row);\n                got_line = 1;\n            }\n            if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {\n                png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,\n                                       s->color_type, s->last_row);\n            }\n            s->y++;\n            if (s->y == s->height) {\n                for(;;) {\n                    if (s->pass == NB_PASSES - 1) {\n                        s->state |= PNG_ALLIMAGE;\n                        goto the_end;\n                    } else {\n                        s->pass++;\n                        s->y = 0;\n                        s->pass_row_size = ff_png_pass_row_size(s->pass,\n                                                             s->bits_per_pixel,\n                                                             s->width);\n                        s->crow_size = s->pass_row_size + 1;\n                        if (s->pass_row_size != 0)\n                            break;\n                    }\n                }\n            }\n        }\n    the_end: ;\n    }\n}', 'static void png_filter_row(DSPContext *dsp, uint8_t *dst, int filter_type,\n                           uint8_t *src, uint8_t *last, int size, int bpp)\n{\n    int i, p, r, g, b, a;\n    switch(filter_type) {\n    case PNG_FILTER_VALUE_NONE:\n        memcpy(dst, src, size);\n        break;\n    case PNG_FILTER_VALUE_SUB:\n        for(i = 0; i < bpp; i++) {\n            dst[i] = src[i];\n        }\n        if(bpp == 4) {\n            p = *(int*)dst;\n            for(; i < size; i+=bpp) {\n                int s = *(int*)(src+i);\n                p = ((s&0x7f7f7f7f) + (p&0x7f7f7f7f)) ^ ((s^p)&0x80808080);\n                *(int*)(dst+i) = p;\n            }\n        } else {\n#define OP_SUB(x,s,l) x+s\n            UNROLL_FILTER(OP_SUB);\n        }\n        break;\n    case PNG_FILTER_VALUE_UP:\n        dsp->add_bytes_l2(dst, src, last, size);\n        break;\n    case PNG_FILTER_VALUE_AVG:\n        for(i = 0; i < bpp; i++) {\n            p = (last[i] >> 1);\n            dst[i] = p + src[i];\n        }\n#define OP_AVG(x,s,l) (((x + l) >> 1) + s) & 0xff\n        UNROLL_FILTER(OP_AVG);\n        break;\n    case PNG_FILTER_VALUE_PAETH:\n        for(i = 0; i < bpp; i++) {\n            p = last[i];\n            dst[i] = p + src[i];\n        }\n        if(bpp > 1 && size > 4) {\n            int w = bpp==4 ? size : size-3;\n            dsp->add_png_paeth_prediction(dst+i, src+i, last+i, w-i, bpp);\n            i = w;\n        }\n        ff_add_png_paeth_prediction(dst+i, src+i, last+i, size-i, bpp);\n        break;\n    }\n}']