Merge commit '1720791e36f9cc24c05efea5bb275ab52156ce50'
authorHendrik Leppkes <h.leppkes@gmail.com>
Mon, 2 Nov 2015 10:50:35 +0000 (11:50 +0100)
committerHendrik Leppkes <h.leppkes@gmail.com>
Mon, 2 Nov 2015 10:50:35 +0000 (11:50 +0100)
* commit '1720791e36f9cc24c05efea5bb275ab52156ce50':
  png: read and write stereo3d frame side data information

Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
1  2 
libavcodec/pngdec.c

   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 -#include "libavutil/avstring.h"
 +//#define DEBUG
 +
 +#include "libavutil/avassert.h"
 +#include "libavutil/bprint.h"
  #include "libavutil/imgutils.h"
  #include "libavutil/stereo3d.h"
  #include "avcodec.h"
  #include "bytestream.h"
  #include "internal.h"
@@@ -1122,83 -458,172 +1123,84 @@@ static int decode_frame_common(AVCodecC
                  ((tag >> 8) & 0xff),
                  ((tag >> 16) & 0xff),
                  ((tag >> 24) & 0xff), length);
 +
 +        if (avctx->codec_id == AV_CODEC_ID_PNG &&
 +            avctx->skip_frame == AVDISCARD_ALL) {
 +            switch(tag) {
 +            case MKTAG('I', 'H', 'D', 'R'):
 +            case MKTAG('p', 'H', 'Y', 's'):
 +            case MKTAG('t', 'E', 'X', 't'):
 +            case MKTAG('I', 'D', 'A', 'T'):
 +                break;
 +            default:
 +                goto skip_tag;
 +            }
 +        }
 +
          switch (tag) {
          case MKTAG('I', 'H', 'D', 'R'):
 -            if (length != 13)
 +            if ((ret = decode_ihdr_chunk(avctx, s, length)) < 0)
                  goto fail;
 -            s->width  = bytestream2_get_be32(&s->gb);
 -            s->height = bytestream2_get_be32(&s->gb);
 -            if (av_image_check_size(s->width, s->height, 0, avctx)) {
 -                s->width = s->height = 0;
 +            break;
 +        case MKTAG('p', 'H', 'Y', 's'):
 +            if ((ret = decode_phys_chunk(avctx, s)) < 0)
                  goto fail;
 -            }
 -            s->bit_depth        = bytestream2_get_byte(&s->gb);
 -            s->color_type       = bytestream2_get_byte(&s->gb);
 -            s->compression_type = bytestream2_get_byte(&s->gb);
 -            s->filter_type      = bytestream2_get_byte(&s->gb);
 -            s->interlace_type   = bytestream2_get_byte(&s->gb);
 -            bytestream2_skip(&s->gb, 4); /* crc */
 -            s->state |= PNG_IHDR;
 -            ff_dlog(avctx, "width=%d height=%d depth=%d color_type=%d "
 -                           "compression_type=%d filter_type=%d interlace_type=%d\n",
 -                    s->width, s->height, s->bit_depth, s->color_type,
 -                    s->compression_type, s->filter_type, s->interlace_type);
              break;
 -        case MKTAG('I', 'D', 'A', 'T'):
 -            if (!(s->state & PNG_IHDR))
 +        case MKTAG('f', 'c', 'T', 'L'):
 +            if (!CONFIG_APNG_DECODER || avctx->codec_id != AV_CODEC_ID_APNG)
 +                goto skip_tag;
 +            if ((ret = decode_fctl_chunk(avctx, s, length)) < 0)
 +                goto fail;
 +            decode_next_dat = 1;
 +            break;
 +        case MKTAG('f', 'd', 'A', 'T'):
 +            if (!CONFIG_APNG_DECODER || avctx->codec_id != AV_CODEC_ID_APNG)
 +                goto skip_tag;
 +            if (!decode_next_dat) {
 +                ret = AVERROR_INVALIDDATA;
                  goto fail;
 -            if (!(s->state & PNG_IDAT)) {
 -                /* init image info */
 -                avctx->width  = s->width;
 -                avctx->height = s->height;
 -
 -                s->channels       = ff_png_get_nb_channels(s->color_type);
 -                s->bits_per_pixel = s->bit_depth * s->channels;
 -                s->bpp            = (s->bits_per_pixel + 7) >> 3;
 -                s->row_size       = (avctx->width * s->bits_per_pixel + 7) >> 3;
 -
 -                if (s->bit_depth == 8 &&
 -                    s->color_type == PNG_COLOR_TYPE_RGB) {
 -                    avctx->pix_fmt = AV_PIX_FMT_RGB24;
 -                } else if (s->bit_depth == 8 &&
 -                           s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
 -                    avctx->pix_fmt = AV_PIX_FMT_RGB32;
 -                } else if (s->bit_depth == 8 &&
 -                           s->color_type == PNG_COLOR_TYPE_GRAY) {
 -                    avctx->pix_fmt = AV_PIX_FMT_GRAY8;
 -                } else if (s->bit_depth == 16 &&
 -                           s->color_type == PNG_COLOR_TYPE_GRAY) {
 -                    avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
 -                } else if (s->bit_depth == 16 &&
 -                           s->color_type == PNG_COLOR_TYPE_RGB) {
 -                    avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
 -                } else if (s->bit_depth == 1 &&
 -                           s->color_type == PNG_COLOR_TYPE_GRAY) {
 -                    avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
 -                } else if (s->bit_depth == 8 &&
 -                           s->color_type == PNG_COLOR_TYPE_PALETTE) {
 -                    avctx->pix_fmt = AV_PIX_FMT_PAL8;
 -                } else if (s->bit_depth == 8 &&
 -                           s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
 -                    avctx->pix_fmt = AV_PIX_FMT_YA8;
 -                } else if (s->bit_depth == 16 &&
 -                           s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
 -                    avctx->pix_fmt = AV_PIX_FMT_YA16BE;
 -                } else {
 -                    goto fail;
 -                }
 -
 -                if (ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF) < 0) {
 -                    av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -                    goto fail;
 -                }
 -                p->pict_type        = AV_PICTURE_TYPE_I;
 -                p->key_frame        = 1;
 -                p->interlaced_frame = !!s->interlace_type;
 -
 -                /* compute the compressed row size */
 -                if (!s->interlace_type) {
 -                    s->crow_size = s->row_size + 1;
 -                } else {
 -                    s->pass          = 0;
 -                    s->pass_row_size = ff_png_pass_row_size(s->pass,
 -                                                            s->bits_per_pixel,
 -                                                            s->width);
 -                    s->crow_size = s->pass_row_size + 1;
 -                }
 -                ff_dlog(avctx, "row_size=%d crow_size =%d\n",
 -                        s->row_size, s->crow_size);
 -                s->image_buf      = p->data[0];
 -                s->image_linesize = p->linesize[0];
 -                /* copy the palette if needed */
 -                if (s->color_type == PNG_COLOR_TYPE_PALETTE)
 -                    memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
 -                /* empty row is used if differencing to the first row */
 -                s->last_row = av_mallocz(s->row_size);
 -                if (!s->last_row)
 -                    goto fail;
 -                if (s->interlace_type ||
 -                    s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
 -                    s->tmp_row = av_malloc(s->row_size);
 -                    if (!s->tmp_row)
 -                        goto fail;
 -                }
 -                /* compressed row */
 -                crow_buf_base = av_malloc(s->row_size + 16);
 -                if (!crow_buf_base)
 -                    goto fail;
 -
 -                /* we want crow_buf+1 to be 16-byte aligned */
 -                s->crow_buf          = crow_buf_base + 15;
 -                s->zstream.avail_out = s->crow_size;
 -                s->zstream.next_out  = s->crow_buf;
              }
 -            s->state |= PNG_IDAT;
 -            if (png_decode_idat(s, length) < 0)
 +            bytestream2_get_be32(&s->gb);
 +            length -= 4;
 +            /* fallthrough */
 +        case MKTAG('I', 'D', 'A', 'T'):
 +            if (CONFIG_APNG_DECODER && avctx->codec_id == AV_CODEC_ID_APNG && !decode_next_dat)
 +                goto skip_tag;
 +            if ((ret = decode_idat_chunk(avctx, s, length, p)) < 0)
                  goto fail;
 -            bytestream2_skip(&s->gb, 4); /* crc */
              break;
          case MKTAG('P', 'L', 'T', 'E'):
 -        {
 -            int n, i, r, g, b;
 -
 -            if ((length % 3) != 0 || length > 256 * 3)
 +            if (decode_plte_chunk(avctx, s, length) < 0)
                  goto skip_tag;
 -            /* read the palette */
 -            n = length / 3;
 -            for (i = 0; i < n; i++) {
 -                r = bytestream2_get_byte(&s->gb);
 -                g = bytestream2_get_byte(&s->gb);
 -                b = bytestream2_get_byte(&s->gb);
 -                s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
 -            }
 -            for (; i < 256; i++)
 -                s->palette[i] = (0xff << 24);
 -            s->state |= PNG_PLTE;
 -            bytestream2_skip(&s->gb, 4);     /* crc */
 -        }
 -        break;
 +            break;
          case MKTAG('t', 'R', 'N', 'S'):
 -        {
 -            int v, i;
 -
 -            /* read the transparency. XXX: Only palette mode supported */
 -            if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
 -                length > 256 ||
 -                !(s->state & PNG_PLTE))
 +            if (decode_trns_chunk(avctx, s, length) < 0)
                  goto skip_tag;
 -            for (i = 0; i < length; i++) {
 -                v = bytestream2_get_byte(&s->gb);
 -                s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
 -            }
 -            bytestream2_skip(&s->gb, 4);     /* crc */
 -        }
 -        break;
 +            break;
 +        case MKTAG('t', 'E', 'X', 't'):
 +            if (decode_text_chunk(s, length, 0, &metadata) < 0)
 +                av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n");
 +            bytestream2_skip(&s->gb, length + 4);
 +            break;
 +        case MKTAG('z', 'T', 'X', 't'):
 +            if (decode_text_chunk(s, length, 1, &metadata) < 0)
 +                av_log(avctx, AV_LOG_WARNING, "Broken zTXt chunk\n");
 +            bytestream2_skip(&s->gb, length + 4);
 +            break;
          case MKTAG('s', 'T', 'E', 'R'): {
+             int mode = bytestream2_get_byte(&s->gb);
              AVStereo3D *stereo3d = av_stereo3d_create_side_data(p);
-             if (!stereo3d) {
+             if (!stereo3d)
 -                goto the_end;
 +                goto fail;
-             } else if (*s->gb.buffer == 0) {
-                 stereo3d->type  = AV_STEREO3D_SIDEBYSIDE;
-                 stereo3d->flags = AV_STEREO3D_FLAG_INVERT;
-             } else if (*s->gb.buffer == 1) {
+             if (mode == 0 || mode == 1) {
                  stereo3d->type  = AV_STEREO3D_SIDEBYSIDE;
+                 stereo3d->flags = mode ? 0 : AV_STEREO3D_FLAG_INVERT;
              } else {
-                  av_log(avctx, AV_LOG_WARNING, "Broken sTER chunk - unknown value\n");
+                  av_log(avctx, AV_LOG_WARNING,
+                         "Unknown value in sTER chunk (%d)\n", mode);
              }
-             bytestream2_skip(&s->gb, length + 4);
+             bytestream2_skip(&s->gb, 4); /* crc */
              break;
          }
          case MKTAG('I', 'E', 'N', 'D'):