mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-28 20:53:54 +02:00
avcodec/pngdec: create a function to decode IDAT chunk.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
3f1eaf590c
commit
b35fa04152
@ -563,6 +563,114 @@ static int decode_phys_chunk(AVCodecContext *avctx, PNGDecContext *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
uint32_t length, AVFrame *p)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!(s->state & PNG_IHDR)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "IDAT without IHDR\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
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 == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
|
||||
s->color_type == PNG_COLOR_TYPE_RGB) {
|
||||
avctx->pix_fmt = AV_PIX_FMT_RGB24;
|
||||
} else if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
|
||||
s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
avctx->pix_fmt = AV_PIX_FMT_RGBA;
|
||||
} else if ((s->bit_depth == 2 || s->bit_depth == 4 || 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 == 16 &&
|
||||
s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
|
||||
} else if ((s->bits_per_pixel == 1 || s->bits_per_pixel == 2 || s->bits_per_pixel == 4 || s->bits_per_pixel == 8) &&
|
||||
s->color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
avctx->pix_fmt = AV_PIX_FMT_PAL8;
|
||||
} else if (s->bit_depth == 1 && s->bits_per_pixel == 1) {
|
||||
avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
|
||||
} 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 {
|
||||
av_log(avctx, AV_LOG_ERROR, "unsupported bit depth %d "
|
||||
"and color type %d\n",
|
||||
s->bit_depth, s->color_type);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
av_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 (avctx->pix_fmt == AV_PIX_FMT_PAL8)
|
||||
memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
|
||||
/* 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)
|
||||
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)
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
/* compressed row */
|
||||
av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16);
|
||||
if (!s->buffer)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
/* we want crow_buf+1 to be 16-byte aligned */
|
||||
s->crow_buf = s->buffer + 15;
|
||||
s->zstream.avail_out = s->crow_size;
|
||||
s->zstream.next_out = s->crow_buf;
|
||||
}
|
||||
s->state |= PNG_IDAT;
|
||||
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)
|
||||
@ -632,105 +740,8 @@ static int decode_frame_png(AVCodecContext *avctx,
|
||||
goto fail;
|
||||
break;
|
||||
case MKTAG('I', 'D', 'A', 'T'):
|
||||
if (!(s->state & PNG_IHDR)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "IDAT without IHDR\n");
|
||||
if (decode_idat_chunk(avctx, s, length, p) < 0)
|
||||
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 == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
|
||||
s->color_type == PNG_COLOR_TYPE_RGB) {
|
||||
avctx->pix_fmt = AV_PIX_FMT_RGB24;
|
||||
} else if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
|
||||
s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
avctx->pix_fmt = AV_PIX_FMT_RGBA;
|
||||
} else if ((s->bit_depth == 2 || s->bit_depth == 4 || 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 == 16 &&
|
||||
s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
|
||||
} else if ((s->bits_per_pixel == 1 || s->bits_per_pixel == 2 || s->bits_per_pixel == 4 || s->bits_per_pixel == 8) &&
|
||||
s->color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
avctx->pix_fmt = AV_PIX_FMT_PAL8;
|
||||
} else if (s->bit_depth == 1 && s->bits_per_pixel == 1) {
|
||||
avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
|
||||
} 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 {
|
||||
av_log(avctx, AV_LOG_ERROR, "unsupported bit depth %d "
|
||||
"and color type %d\n",
|
||||
s->bit_depth, s->color_type);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF) < 0)
|
||||
goto fail;
|
||||
ff_thread_finish_setup(avctx);
|
||||
|
||||
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;
|
||||
}
|
||||
av_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 (avctx->pix_fmt == AV_PIX_FMT_PAL8)
|
||||
memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
/* compressed row */
|
||||
av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16);
|
||||
if (!s->buffer)
|
||||
goto fail;
|
||||
|
||||
/* we want crow_buf+1 to be 16-byte aligned */
|
||||
s->crow_buf = s->buffer + 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)
|
||||
goto fail;
|
||||
bytestream2_skip(&s->gb, 4); /* crc */
|
||||
break;
|
||||
case MKTAG('P', 'L', 'T', 'E'):
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user