Commit b35fa041 authored by Benoit Fouet's avatar Benoit Fouet Committed by Michael Niedermayer

avcodec/pngdec: create a function to decode IDAT chunk.

Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 3f1eaf59
......@@ -563,78 +563,14 @@ static int decode_phys_chunk(AVCodecContext *avctx, PNGDecContext *s)
return 0;
}
static int decode_frame_png(AVCodecContext *avctx,
void *data, int *got_frame,
AVPacket *avpkt)
static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
uint32_t length, AVFrame *p)
{
PNGDecContext *const s = avctx->priv_data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
AVFrame *p;
AVDictionary *metadata = NULL;
uint32_t tag, length;
int64_t sig;
int ret;
ff_thread_release_buffer(avctx, &s->last_picture);
FFSWAP(ThreadFrame, s->picture, s->last_picture);
p = s->picture.f;
bytestream2_init(&s->gb, buf, buf_size);
/* check signature */
sig = bytestream2_get_be64(&s->gb);
if (sig != PNGSIG &&
sig != MNGSIG) {
av_log(avctx, AV_LOG_ERROR, "Missing png signature\n");
return AVERROR_INVALIDDATA;
}
s->y = s->state = 0;
/* init the zlib */
s->zstream.zalloc = ff_png_zalloc;
s->zstream.zfree = ff_png_zfree;
s->zstream.opaque = NULL;
ret = inflateInit(&s->zstream);
if (ret != Z_OK) {
av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret);
return AVERROR_EXTERNAL;
}
for (;;) {
if (bytestream2_get_bytes_left(&s->gb) <= 0) {
av_log(avctx, AV_LOG_ERROR, "%d bytes left\n", bytestream2_get_bytes_left(&s->gb));
if ( s->state & PNG_ALLIMAGE
&& avctx->strict_std_compliance <= FF_COMPLIANCE_NORMAL)
goto exit_loop;
goto fail;
}
length = bytestream2_get_be32(&s->gb);
if (length > 0x7fffffff || length > bytestream2_get_bytes_left(&s->gb)) {
av_log(avctx, AV_LOG_ERROR, "chunk too big\n");
goto fail;
}
tag = bytestream2_get_le32(&s->gb);
if (avctx->debug & FF_DEBUG_STARTCODE)
av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
(tag & 0xff),
((tag >> 8) & 0xff),
((tag >> 16) & 0xff),
((tag >> 24) & 0xff), length);
switch (tag) {
case MKTAG('I', 'H', 'D', 'R'):
if (decode_ihdr_chunk(avctx, s, length) < 0)
goto fail;
break;
case MKTAG('p', 'H', 'Y', 's'):
if (decode_phys_chunk(avctx, s) < 0)
goto fail;
break;
case MKTAG('I', 'D', 'A', 'T'):
if (!(s->state & PNG_IHDR)) {
av_log(avctx, AV_LOG_ERROR, "IDAT without IHDR\n");
goto fail;
return AVERROR_INVALIDDATA;
}
if (!(s->state & PNG_IDAT)) {
/* init image info */
......@@ -679,11 +615,11 @@ static int decode_frame_png(AVCodecContext *avctx,
av_log(avctx, AV_LOG_ERROR, "unsupported bit depth %d "
"and color type %d\n",
s->bit_depth, s->color_type);
goto fail;
return AVERROR_INVALIDDATA;
}
if (ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF) < 0)
goto fail;
if ((ret = ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF)) < 0)
return ret;
ff_thread_finish_setup(avctx);
p->pict_type = AV_PICTURE_TYPE_I;
......@@ -710,17 +646,17 @@ static int decode_frame_png(AVCodecContext *avctx,
/* empty row is used if differencing to the first row */
av_fast_padded_mallocz(&s->last_row, &s->last_row_size, s->row_size);
if (!s->last_row)
goto fail;
return AVERROR_INVALIDDATA;
if (s->interlace_type ||
s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
av_fast_padded_malloc(&s->tmp_row, &s->tmp_row_size, s->row_size);
if (!s->tmp_row)
goto fail;
return AVERROR_INVALIDDATA;
}
/* compressed row */
av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16);
if (!s->buffer)
goto fail;
return AVERROR(ENOMEM);
/* we want crow_buf+1 to be 16-byte aligned */
s->crow_buf = s->buffer + 15;
......@@ -728,9 +664,84 @@ static int decode_frame_png(AVCodecContext *avctx,
s->zstream.next_out = s->crow_buf;
}
s->state |= PNG_IDAT;
if (png_decode_idat(s, length) < 0)
goto fail;
if ((ret = png_decode_idat(s, length)) < 0)
return ret;
bytestream2_skip(&s->gb, 4); /* crc */
return 0;
}
static int decode_frame_png(AVCodecContext *avctx,
void *data, int *got_frame,
AVPacket *avpkt)
{
PNGDecContext *const s = avctx->priv_data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
AVFrame *p;
AVDictionary *metadata = NULL;
uint32_t tag, length;
int64_t sig;
int ret;
ff_thread_release_buffer(avctx, &s->last_picture);
FFSWAP(ThreadFrame, s->picture, s->last_picture);
p = s->picture.f;
bytestream2_init(&s->gb, buf, buf_size);
/* check signature */
sig = bytestream2_get_be64(&s->gb);
if (sig != PNGSIG &&
sig != MNGSIG) {
av_log(avctx, AV_LOG_ERROR, "Missing png signature\n");
return AVERROR_INVALIDDATA;
}
s->y = s->state = 0;
/* init the zlib */
s->zstream.zalloc = ff_png_zalloc;
s->zstream.zfree = ff_png_zfree;
s->zstream.opaque = NULL;
ret = inflateInit(&s->zstream);
if (ret != Z_OK) {
av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret);
return AVERROR_EXTERNAL;
}
for (;;) {
if (bytestream2_get_bytes_left(&s->gb) <= 0) {
av_log(avctx, AV_LOG_ERROR, "%d bytes left\n", bytestream2_get_bytes_left(&s->gb));
if ( s->state & PNG_ALLIMAGE
&& avctx->strict_std_compliance <= FF_COMPLIANCE_NORMAL)
goto exit_loop;
goto fail;
}
length = bytestream2_get_be32(&s->gb);
if (length > 0x7fffffff || length > bytestream2_get_bytes_left(&s->gb)) {
av_log(avctx, AV_LOG_ERROR, "chunk too big\n");
goto fail;
}
tag = bytestream2_get_le32(&s->gb);
if (avctx->debug & FF_DEBUG_STARTCODE)
av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
(tag & 0xff),
((tag >> 8) & 0xff),
((tag >> 16) & 0xff),
((tag >> 24) & 0xff), length);
switch (tag) {
case MKTAG('I', 'H', 'D', 'R'):
if (decode_ihdr_chunk(avctx, s, length) < 0)
goto fail;
break;
case MKTAG('p', 'H', 'Y', 's'):
if (decode_phys_chunk(avctx, s) < 0)
goto fail;
break;
case MKTAG('I', 'D', 'A', 'T'):
if (decode_idat_chunk(avctx, s, length, p) < 0)
goto fail;
break;
case MKTAG('P', 'L', 'T', 'E'):
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment