]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/pngdec.c
Merge commit 'a97563c889fefd81ad6b3758471434d8c2e2e550'
[ffmpeg] / libavcodec / pngdec.c
index 083f61f4f802f240b3694fca2f12d134925e6b96..0d6612cccafb897e1518848e6d6755b564e5998c 100644 (file)
@@ -836,6 +836,49 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
     return 0;
 }
 
+static int decode_iccp_chunk(PNGDecContext *s, int length, AVFrame *f)
+{
+    int ret, cnt = 0;
+    uint8_t *data, profile_name[82];
+    AVBPrint bp;
+    AVFrameSideData *sd;
+
+    while ((profile_name[cnt++] = bytestream2_get_byte(&s->gb)) && cnt < 81);
+    if (cnt > 80) {
+        av_log(s->avctx, AV_LOG_ERROR, "iCCP with invalid name!\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    length = FFMAX(length - cnt, 0);
+
+    if (bytestream2_get_byte(&s->gb) != 0) {
+        av_log(s->avctx, AV_LOG_ERROR, "iCCP with invalid compression!\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    length = FFMAX(length - 1, 0);
+
+    if ((ret = decode_zbuf(&bp, s->gb.buffer, s->gb.buffer + length)) < 0)
+        return ret;
+
+    av_bprint_finalize(&bp, (char **)&data);
+
+    sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, bp.len);
+    if (!sd) {
+        av_free(data);
+        return AVERROR(ENOMEM);
+    }
+
+    av_dict_set(&sd->metadata, "name", profile_name, 0);
+    memcpy(sd->data, data, bp.len);
+    av_free(data);
+
+    /* ICC compressed data and CRC */
+    bytestream2_skip(&s->gb, length + 4);
+
+    return 0;
+}
+
 static void handle_small_bpp(PNGDecContext *s, AVFrame *p)
 {
     if (s->bits_per_pixel == 1 && s->color_type == PNG_COLOR_TYPE_PALETTE) {
@@ -1239,6 +1282,11 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
             bytestream2_skip(&s->gb, 4); /* crc */
             break;
         }
+        case MKTAG('i', 'C', 'C', 'P'): {
+            if (decode_iccp_chunk(s, length, p) < 0)
+                goto fail;
+            break;
+        }
         case MKTAG('I', 'E', 'N', 'D'):
             if (!(s->pic_state & PNG_ALLIMAGE))
                 av_log(avctx, AV_LOG_ERROR, "IEND without all image\n");
@@ -1366,7 +1414,7 @@ static int decode_frame_png(AVCodecContext *avctx,
     }
 
     if ((ret = av_frame_ref(data, s->picture.f)) < 0)
-        return ret;
+        goto the_end;
 
     *got_frame = 1;