@ -36,6 +36,16 @@
# include <zlib.h>
enum PNGHeaderState {
PNG_IHDR = 1 < < 0 ,
PNG_PLTE = 1 < < 1 ,
} ;
enum PNGImageState {
PNG_IDAT = 1 < < 0 ,
PNG_ALLIMAGE = 1 < < 1 ,
} ;
typedef struct PNGDecContext {
PNGDSPContext dsp ;
AVCodecContext * avctx ;
@ -45,7 +55,8 @@ typedef struct PNGDecContext {
ThreadFrame last_picture ;
ThreadFrame picture ;
int state ;
enum PNGHeaderState hdr_state ;
enum PNGImageState pic_state ;
int width , height ;
int cur_w , cur_h ;
int last_w , last_h ;
@ -334,7 +345,7 @@ static void png_handle_row(PNGDecContext *s)
}
s - > y + + ;
if ( s - > y = = s - > cur_h ) {
s - > state | = PNG_ALLIMAGE ;
s - > pic_ state | = PNG_ALLIMAGE ;
if ( s - > filter_type = = PNG_FILTER_TYPE_LOCO ) {
if ( s - > bit_depth = = 16 ) {
deloco_rgb16 ( ( uint16_t * ) ptr , s - > row_size / 2 ,
@ -369,7 +380,7 @@ static void png_handle_row(PNGDecContext *s)
memset ( s - > last_row , 0 , s - > row_size ) ;
for ( ; ; ) {
if ( s - > pass = = NB_PASSES - 1 ) {
s - > state | = PNG_ALLIMAGE ;
s - > pic_ state | = PNG_ALLIMAGE ;
goto the_end ;
} else {
s - > pass + + ;
@ -404,7 +415,7 @@ static int png_decode_idat(PNGDecContext *s, int length)
return AVERROR_EXTERNAL ;
}
if ( s - > zstream . avail_out = = 0 ) {
if ( ! ( s - > state & PNG_ALLIMAGE ) ) {
if ( ! ( s - > pic_ state & PNG_ALLIMAGE ) ) {
png_handle_row ( s ) ;
}
s - > zstream . avail_out = s - > crow_size ;
@ -541,12 +552,12 @@ static int decode_ihdr_chunk(AVCodecContext *avctx, PNGDecContext *s,
if ( length ! = 13 )
return AVERROR_INVALIDDATA ;
if ( s - > state & PNG_IDAT ) {
if ( s - > pic_ state & PNG_IDAT ) {
av_log ( avctx , AV_LOG_ERROR , " IHDR after IDAT \n " ) ;
return AVERROR_INVALIDDATA ;
}
if ( s - > state & PNG_IHDR ) {
if ( s - > hdr_ state & PNG_IHDR ) {
av_log ( avctx , AV_LOG_ERROR , " Multiple IHDR \n " ) ;
return AVERROR_INVALIDDATA ;
}
@ -569,7 +580,7 @@ static int decode_ihdr_chunk(AVCodecContext *avctx, PNGDecContext *s,
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 ;
s - > hdr_ state | = PNG_IHDR ;
if ( avctx - > debug & FF_DEBUG_PICT_INFO )
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 " ,
@ -585,7 +596,7 @@ error:
static int decode_phys_chunk ( AVCodecContext * avctx , PNGDecContext * s )
{
if ( s - > state & PNG_IDAT ) {
if ( s - > pic_ state & PNG_IDAT ) {
av_log ( avctx , AV_LOG_ERROR , " pHYs after IDAT \n " ) ;
return AVERROR_INVALIDDATA ;
}
@ -605,11 +616,11 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
int ret ;
size_t byte_depth = s - > bit_depth > 8 ? 2 : 1 ;
if ( ! ( s - > state & PNG_IHDR ) ) {
if ( ! ( s - > hdr_ state & PNG_IHDR ) ) {
av_log ( avctx , AV_LOG_ERROR , " IDAT without IHDR \n " ) ;
return AVERROR_INVALIDDATA ;
}
if ( ! ( s - > state & PNG_IDAT ) ) {
if ( ! ( s - > pic_ state & PNG_IDAT ) ) {
/* init image info */
avctx - > width = s - > width ;
avctx - > height = s - > height ;
@ -734,7 +745,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
s - > zstream . next_out = s - > crow_buf ;
}
s - > state | = PNG_IDAT ;
s - > pic_ state | = PNG_IDAT ;
/* set image to non-transparent bpp while decompressing */
if ( s - > has_trns & & s - > color_type ! = PNG_COLOR_TYPE_PALETTE )
@ -770,7 +781,7 @@ static int decode_plte_chunk(AVCodecContext *avctx, PNGDecContext *s,
}
for ( ; i < 256 ; i + + )
s - > palette [ i ] = ( 0xFFU < < 24 ) ;
s - > state | = PNG_PLTE ;
s - > hdr_ state | = PNG_PLTE ;
bytestream2_skip ( & s - > gb , 4 ) ; /* crc */
return 0 ;
@ -781,18 +792,18 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
{
int v , i ;
if ( ! ( s - > state & PNG_IHDR ) ) {
if ( ! ( s - > hdr_ state & PNG_IHDR ) ) {
av_log ( avctx , AV_LOG_ERROR , " trns before IHDR \n " ) ;
return AVERROR_INVALIDDATA ;
}
if ( s - > state & PNG_IDAT ) {
if ( s - > pic_ state & PNG_IDAT ) {
av_log ( avctx , AV_LOG_ERROR , " trns after IDAT \n " ) ;
return AVERROR_INVALIDDATA ;
}
if ( s - > color_type = = PNG_COLOR_TYPE_PALETTE ) {
if ( length > 256 | | ! ( s - > state & PNG_PLTE ) )
if ( length > 256 | | ! ( s - > hdr_ state & PNG_PLTE ) )
return AVERROR_INVALIDDATA ;
for ( i = 0 ; i < length ; i + + ) {
@ -906,7 +917,7 @@ static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s,
if ( length ! = 26 )
return AVERROR_INVALIDDATA ;
if ( ! ( s - > state & PNG_IHDR ) ) {
if ( ! ( s - > hdr_ state & PNG_IHDR ) ) {
av_log ( avctx , AV_LOG_ERROR , " fctl before IHDR \n " ) ;
return AVERROR_INVALIDDATA ;
}
@ -1122,13 +1133,13 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
}
if ( CONFIG_APNG_DECODER & & avctx - > codec_id = = AV_CODEC_ID_APNG & & length = = 0 ) {
if ( ! ( s - > state & PNG_IDAT ) )
if ( ! ( s - > pic_ state & PNG_IDAT ) )
return 0 ;
else
goto exit_loop ;
}
av_log ( avctx , AV_LOG_ERROR , " %d bytes left \n " , length ) ;
if ( s - > state & PNG_ALLIMAGE
if ( s - > pic_ state & PNG_ALLIMAGE
& & avctx - > strict_std_compliance < = FF_COMPLIANCE_NORMAL )
goto exit_loop ;
ret = AVERROR_INVALIDDATA ;
@ -1228,9 +1239,9 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
break ;
}
case MKTAG ( ' I ' , ' E ' , ' N ' , ' D ' ) :
if ( ! ( s - > state & PNG_ALLIMAGE ) )
if ( ! ( s - > pic_ state & PNG_ALLIMAGE ) )
av_log ( avctx , AV_LOG_ERROR , " IEND without all image \n " ) ;
if ( ! ( s - > state & ( PNG_ALLIMAGE | PNG_IDAT ) ) ) {
if ( ! ( s - > pic_ state & ( PNG_ALLIMAGE | PNG_IDAT ) ) ) {
ret = AVERROR_INVALIDDATA ;
goto fail ;
}
@ -1330,7 +1341,9 @@ static int decode_frame_png(AVCodecContext *avctx,
return AVERROR_INVALIDDATA ;
}
s - > y = s - > state = s - > has_trns = 0 ;
s - > y = s - > has_trns = 0 ;
s - > hdr_state = 0 ;
s - > pic_state = 0 ;
/* init the zlib */
s - > zstream . zalloc = ff_png_zalloc ;
@ -1377,7 +1390,7 @@ static int decode_frame_apng(AVCodecContext *avctx,
FFSWAP ( ThreadFrame , s - > picture , s - > last_picture ) ;
p = s - > picture . f ;
if ( ! ( s - > state & PNG_IHDR ) ) {
if ( ! ( s - > hdr_ state & PNG_IHDR ) ) {
if ( ! avctx - > extradata_size )
return AVERROR_INVALIDDATA ;
@ -1397,14 +1410,14 @@ static int decode_frame_apng(AVCodecContext *avctx,
goto end ;
}
s - > y = 0 ;
s - > state & = ~ ( PNG_IDAT | PNG_ALLIMAGE ) ;
s - > pic_state = 0 ;
bytestream2_init ( & s - > gb , avpkt - > data , avpkt - > size ) ;
if ( ( ret = decode_frame_common ( avctx , s , p , avpkt ) ) < 0 )
goto end ;
if ( ! ( s - > state & PNG_ALLIMAGE ) )
if ( ! ( s - > pic_ state & PNG_ALLIMAGE ) )
av_log ( avctx , AV_LOG_WARNING , " Frame did not contain a complete image \n " ) ;
if ( ! ( s - > state & ( PNG_ALLIMAGE | PNG_IDAT ) ) ) {
if ( ! ( s - > pic_ state & ( PNG_ALLIMAGE | PNG_IDAT ) ) ) {
ret = AVERROR_INVALIDDATA ;
goto end ;
}
@ -1453,7 +1466,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
memcpy ( pdst - > palette , psrc - > palette , sizeof ( pdst - > palette ) ) ;
pdst - > state | = psrc - > state & ( PNG_IHDR | PNG_PLTE ) ;
pdst - > hdr_ state | = psrc - > hdr_ state;
ff_thread_release_buffer ( dst , & pdst - > last_picture ) ;
if ( psrc - > last_picture . f - > data [ 0 ] & &