func: static int decode_frame(AVCodecContext void *data, int *got_frame, AVPacket *avpkt) TiffContext * const s = avctx -> AVFrame * const p = ThreadFrame frame = . f = data unsigned off ; int le , ret , plane , planes ; int i , j , entries , stride ; unsigned soff , ssize ; uint8_t * dst ; if ( ret = ff_tdecode_header ( & s -> gb , & le , & off ) )  if ( off >= UINT_MAX - 14 || avpkt -> size < off + 14 )  s -> le = le; s -> bppcount = s -> bpp = 1; s -> photometric = TIFF_PHOTOMETRIC_NONE; s -> compr = TIFF_RAW; s -> fill_order = 0; s -> stripsizesoff = s -> strippos = 0; entries = ff_tget_short ( & s -> gb , le ); if ( bytestream2_get_bytes_left ( & s -> gb ) < entries * 12 )  for (i = 0; i < entries; i++) if ( ( ret = tiff_decode_tag ( s , p ) ) < 0 )  static int tiff_decode_tag(TiffContext *s, AVFrame *frame) unsigned tag , type , count , off , value = 0 , value2 = 0 ; int i , start ; int ret ; double * dp ; ret = ff_tread_tag ( & s -> gb , s -> le , & tag , & type , & count , & start ); if ( ret < 0 )  off = bytestream2_tell ( & s -> gb ); if ( count == 1 )  switch ( type )  value = ff_tget ( & s -> gb , type , s -> le ); value = ff_tget ( & s -> gb , TIFF_LONG , s -> le ); if ( count <= 4 )  value = UINT_MAX; switch ( tag )  s -> width = value; s -> height = value; if ( count > 4U )  return AVERROR_INVALIDDATA ; s -> bppcount = count; if ( count == 1 )  s -> bpp = value; switch ( type )  s -> bpp = 0; if ( bytestream2_get_bytes_left ( & s -> gb ) < type_sizes [ type ] * count )  return AVERROR_INVALIDDATA ; for (i = 0; i < count; i++) s -> bpp += ff_tget ( & s -> gb , type , s -> le ); s -> bpp = - 1; if ( count != 1 )  return AVERROR_INVALIDDATA ; if ( value > 4U )  return AVERROR_INVALIDDATA ; if ( s -> bppcount == 1 )  s -> bpp *= value; s -> bppcount = value; s -> compr = value; s -> predictor = 0; switch ( s -> compr )  s -> fax_opts = 0; return AVERROR_PATCHWELCOME ; return AVERROR_INVALIDDATA ; if ( ! value || ( type == TIFF_LONG && value == UINT_MAX ) )  value = s -> height; s -> rps = FFMIN ( value , s -> height ); if ( count == 1 )  s -> strippos = off; s -> strips = count; if ( s -> strips == 1 )  s -> rps = s -> height; s -> sot = type; if ( count == 1 )  s -> stripsizesoff = off; s -> strips = count; s -> sstype = type; return AVERROR_PATCHWELCOME ; s -> predictor = value; switch ( value )  s -> photometric = value; return AVERROR_PATCHWELCOME ; return AVERROR_INVALIDDATA ; if ( value < 1 || value > 2 )  value = 1; s -> fill_order = value - 1; GetByteContext pal_gb [ 3 ] ; off = type_sizes [ type ]; if ( count / 3 > 256 || bytestream2_get_bytes_left ( & s -> gb ) < count / 3 * off * 3 )  return AVERROR_INVALIDDATA ; pal_gb [ 0 ] = pal_gb [ 1 ] = pal_gb [ 2 ] = s -> gb; off = ( type_sizes [ type ] - 1 ) << 3; for (i = 0; i < count / 3; i++) uint32_t p = 0xFF000000 ; p |= ( ff_tget ( & pal_gb [ 0 ] , type , s -> le ) >> off ) << 16; p |= ( ff_tget ( & pal_gb [ 1 ] , type , s -> le ) >> off ) << 8; p |= ff_tget ( & pal_gb [ 2 ] , type , s -> le ) >> off; s -> palette [ i ] = p; s -> palette_is_set = 1; s -> planar = value == 2; if ( count != 2 )  return AVERROR_INVALIDDATA ; for (i = 0; i < count; i++) s -> subsampling [ i ] = ff_tget ( & s -> gb , type , s -> le ); if ( s -> compr == TIFF_G3 )  s -> fax_opts = value; if ( s -> compr == TIFF_G4 )  s -> fax_opts = value; s -> geotag_count = ff_tget_short ( & s -> gb , s -> le ); if ( s -> geotag_count > count / 4 - 1 )  s -> geotag_count = count / 4 - 1; if ( bytestream2_get_bytes_left ( & s -> gb ) < s -> geotag_count * sizeof ( int16_t ) * 4 )  s -> geotag_count = 0; return - 1 ; s -> geotags = av_mallocz_array ( s -> geotag_count , sizeof ( TiffGeoTag ) ); if ( ! s -> geotags )  s -> geotag_count = 0; for (i = 0; i < s->geotag_count; i++) s -> geotags [ i ] . key = ff_tget_short ( & s -> gb , s -> le ); s -> geotags [ i ] . type = ff_tget_short ( & s -> gb , s -> le ); s -> geotags [ i ] . count = ff_tget_short ( & s -> gb , s -> le ); if ( ! s -> geotags [ i ] . type )  s -> geotags [ i ] . val = get_geokey_val ( s -> geotags [ i ] . key , ff_tget_short ( & s -> gb , s -> le ) ); static char *get_geokey_val(int key, int val) char * ap ; if ( val == TIFF_GEO_KEY_UNDEFINED )  return av_strdup ( "undefined" ) ; if ( val == TIFF_GEO_KEY_USER_DEFINED )  return av_strdup ( "User-Defined" ) ; switch ( key )  ap = av_strdup ( search_keyval ( ff_tiff_proj_cs_type_codes , FF_ARRAY_ELEMS ( ff_tiff_proj_cs_type_codes ) , val ) ); static const char *search_keyval(const TiffGeoTagKeyName *keys, int n, int id) TiffGeoTagKeyName * r = bsearch ( & id , keys , n , sizeof ( keys [ 0 ] ) , cmp_id_key ) ; if ( r )  return r -> name ; return NULL ; if ( ap )  return ap ; ap = av_strdup ( search_keyval ( ff_tiff_projection_codes , FF_ARRAY_ELEMS ( ff_tiff_projection_codes ) , val ) ); static const char *search_keyval(const TiffGeoTagKeyName *keys, int n, int id) TiffGeoTagKeyName * r = bsearch ( & id , keys , n , sizeof ( keys [ 0 ] ) , cmp_id_key ) ; if ( r )  return r -> name ; return NULL ; if ( ap )  return ap ; ap = av_malloc ( 14 ); if ( ap )  snprintf ( ap , 14 , "Unknown-%d" , val ); return ap ; s -> geotags [ i ] . offset = ff_tget_short ( & s -> gb , s -> le ); if ( count >= INT_MAX / sizeof ( int64_t ) )  return AVERROR_INVALIDDATA ; if ( bytestream2_get_bytes_left ( & s -> gb ) < count * sizeof ( int64_t ) )  return AVERROR_INVALIDDATA ; dp = av_malloc_array ( count , sizeof ( double ) ); if ( ! dp )  for (i = 0; i < count; i++) dp [ i ] = ff_tget_double ( & s -> gb , s -> le ); for (i = 0; i < s->geotag_count; i++) if ( s -> geotags [ i ] . type == TIFF_GEO_DOUBLE_PARAMS )  if ( s -> geotags [ i ] . count == 0 || s -> geotags [ i ] . offset + s -> geotags [ i ] . count > count )  char * ap = doubles2str ( & dp [ s -> geotags [ i ] . offset ] , s -> geotags [ i ] . count , ", " ) ; static char *doubles2str(double *dp, int count, const char *sep) int i ; char * ap , * ap0 ; uint64_t component_len ; if ( ! sep )  sep = ", "; component_len = 24L L + strlen ( sep ) if ( count >= ( INT_MAX - 1 ) / component_len )  return NULL ; ap = av_malloc ( component_len * count + 1 ); if ( ! ap )  return NULL ; ap0 = ap; ap [ 0 ] = '\0'; for (i = 0; i < count; i++) unsigned l = snprintf ( ap , component_len , "%.15g%s" , dp [ i ] , sep ) ; if ( l >= component_len )  return NULL ; ap += l; ap0 [ strlen ( ap0 ) - strlen ( sep ) ] = '\0'; return ap0 ; if ( ! ap )  return AVERROR ( ENOMEM ) ; s -> geotags [ i ] . val = ap; for (i = 0; i < s->geotag_count; i++) if ( s -> geotags [ i ] . type == TIFF_GEO_ASCII_PARAMS )  if ( s -> geotags [ i ] . count == 0 || s -> geotags [ i ] . offset + s -> geotags [ i ] . count > count )  char * ap ; if ( bytestream2_get_bytes_left ( & s -> gb ) < s -> geotags [ i ] . count )  return AVERROR_INVALIDDATA ; ap = av_malloc ( s -> geotags [ i ] . count ); if ( ! ap )  return AVERROR ( ENOMEM ) ; ap [ s -> geotags [ i ] . count - 1 ] = '\0'; s -> geotags [ i ] . val = ap; if ( s -> avctx -> err_recognition & AV_EF_EXPLODE )  return AVERROR_INVALIDDATA ; if ( s -> bpp > 64U )  return AVERROR_INVALIDDATA ; return 0 ; for (i = 0; i<s->geotag_count; i++) const char * keyname = get_geokey_name ( s -> geotags [ i ] . key ) ; static const char *get_geokey_name(int key) return NULL ; if ( ! keyname )  if ( get_geokey_type ( s -> geotags [ i ] . key ) != s -> geotags [ i ] . type )  static int get_geokey_type(int key) return AVERROR_INVALIDDATA ; ret = av_dict_set ( avpriv_frame_get_metadatap ( p ) , keyname , s -> geotags [ i ] . val , 0 ); if ( ret < 0 )  if ( ! s -> strippos && ! s -> stripoff )  if ( ( ret = init_image ( s , & frame ) ) < 0 )  static int init_image(TiffContext *s, ThreadFrame *frame) int ret ; if ( s -> bpp >= 100 || s -> bppcount >= 10 )  return AVERROR_INVALIDDATA ; switch ( s -> planar * 1000 + s -> bpp * 10 + s -> bppcount )  if ( ! s -> palette_is_set )  s -> avctx -> pix_fmt = AV_PIX_FMT_MONOBLACK; s -> avctx -> pix_fmt = AV_PIX_FMT_PAL8; s -> avctx -> pix_fmt = s -> palette_is_set ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8; if ( s -> photometric == TIFF_PHOTOMETRIC_YCBCR )  if ( s -> subsampling [ 0 ] == 1 && s -> subsampling [ 1 ] == 1 )  s -> avctx -> pix_fmt = AV_PIX_FMT_YUV444P; if ( s -> subsampling [ 0 ] == 2 && s -> subsampling [ 1 ] == 1 )  s -> avctx -> pix_fmt = AV_PIX_FMT_YUV422P; if ( s -> subsampling [ 0 ] == 4 && s -> subsampling [ 1 ] == 1 )  s -> avctx -> pix_fmt = AV_PIX_FMT_YUV411P; if ( s -> subsampling [ 0 ] == 1 && s -> subsampling [ 1 ] == 2 )  s -> avctx -> pix_fmt = AV_PIX_FMT_YUV440P; if ( s -> subsampling [ 0 ] == 2 && s -> subsampling [ 1 ] == 2 )  s -> avctx -> pix_fmt = AV_PIX_FMT_YUV420P; if ( s -> subsampling [ 0 ] == 4 && s -> subsampling [ 1 ] == 4 )  s -> avctx -> pix_fmt = AV_PIX_FMT_YUV410P; return AVERROR_PATCHWELCOME ; s -> avctx -> pix_fmt = AV_PIX_FMT_RGB24; s -> avctx -> pix_fmt = s -> le ? AV_PIX_FMT_GRAY16LE : AV_PIX_FMT_GRAY16BE; s -> avctx -> pix_fmt = AV_PIX_FMT_YA8; s -> avctx -> pix_fmt = s -> le ? AV_PIX_FMT_YA16LE : AV_PIX_FMT_YA16BE; s -> avctx -> pix_fmt = AV_PIX_FMT_RGBA; s -> avctx -> pix_fmt = s -> le ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB48BE; s -> avctx -> pix_fmt = s -> le ? AV_PIX_FMT_RGBA64LE : AV_PIX_FMT_RGBA64BE; s -> avctx -> pix_fmt = AV_PIX_FMT_GBRP; s -> avctx -> pix_fmt = AV_PIX_FMT_GBRAP; s -> avctx -> pix_fmt = s -> le ? AV_PIX_FMT_GBRP16LE : AV_PIX_FMT_GBRP16BE; s -> avctx -> pix_fmt = s -> le ? AV_PIX_FMT_GBRAP16LE : AV_PIX_FMT_GBRAP16BE; return AVERROR_INVALIDDATA ; if ( s -> photometric == TIFF_PHOTOMETRIC_YCBCR )  const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get ( s -> avctx -> pix_fmt ) ; if ( ( desc -> flags & AV_PIX_FMT_FLAG_RGB ) || ! ( desc -> flags & AV_PIX_FMT_FLAG_PLANAR ) || desc -> nb_components < 3 )  return AVERROR_INVALIDDATA ; if ( s -> width != s -> avctx -> width || s -> height != s -> avctx -> height )  ret = ff_set_dimensions ( s -> avctx , s -> width , s -> height ); if ( ret < 0 )  return ret ; if ( ( ret = ff_thread_get_buffer ( s -> avctx , frame , 0 ) ) < 0 )  return ret ; return 0 ; if ( s -> strips == 1 && ! s -> stripsize )  s -> stripsize = avpkt -> size - s -> stripoff; if ( s -> stripsizesoff )  if ( s -> stripsizesoff >= ( unsigned ) avpkt -> size )  if ( s -> strippos )  if ( s -> strippos >= ( unsigned ) avpkt -> size )  if ( s -> rps <= 0 )  planes = s -> planar ? s -> bppcount : 1; for (plane = 0; plane < planes; plane++) stride = p -> linesize [ plane ]; dst = p -> data [ plane ]; for (i = 0; i < s->height; i += s->rps) if ( s -> stripsizesoff )  ssize = ff_tget ( & stripsizes , s -> sstype , le ); ssize = s -> stripsize; if ( s -> strippos )  soff = ff_tget ( & stripdata , s -> sot , le ); soff = s -> stripoff; if ( soff > avpkt -> size || ssize > avpkt -> size - soff )  if ( ( ret = tiff_unpack_strip ( s , p , dst , stride , avpkt -> data + soff , ssize , i , FFMIN ( s -> rps , s -> height - i ) ) ) < 0 )  if ( avctx -> err_recognition & AV_EF_EXPLODE )  dst += s -> rps * stride; if ( s -> predictor == 2 )  if ( s -> photometric == TIFF_PHOTOMETRIC_YCBCR )  static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int const uint8_t *src, int size, int strip_start, int lines) int width = ( ( s -> width * s -> bpp ) + 7 ) >> 3 ; const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get ( p -> format ) ; int is_yuv = ! ( desc -> flags & AV_PIX_FMT_FLAG_RGB ) && ( desc -> flags & AV_PIX_FMT_FLAG_PLANAR ) && desc -> nb_components >= 3 ; if ( s -> planar )  width /= s -> bppcount; if ( size <= 0 )  if ( is_yuv )  if ( s -> yuv_line == NULL )  dst = s -> yuv_line; stride = 0; width = ( s -> width - 1 ) / s -> subsampling [ 0 ] + 1; width = width * s -> subsampling [ 0 ] * s -> subsampling [ 1 ] + 2 * width; if ( s -> compr == TIFF_DEFLATE || s -> compr == TIFF_ADOBE_DEFLATE )  return tiff_unpack_zlib ( s , p , dst , stride , src , size , width , lines , strip_start , is_yuv ) ; static int tiff_unpack_zlib(TiffContext *s, AVFrame *p, uint8_t *dst, int const uint8_t *src, int size, int width, int int strip_start, int is_yuv) uint8_t * zbuf ; unsigned long outlen ; int ret , line ; outlen = width * lines; zbuf = av_malloc ( outlen ); if ( ! zbuf )  if ( s -> fill_order )  if ( ( ret = deinvert_buffer ( s , src , size ) ) < 0 )  static int deinvert_buffer(TiffContext *s, const uint8_t *src, int size) if ( ! s -> deinvert_buf )  return AVERROR ( ENOMEM ) ; return 0 ; src = s -> deinvert_buf; ret = tiff_uncompress ( zbuf , & outlen , src , size ); static int tiff_uncompress(uint8_t *dst, unsigned long *len, const uint8_t int size) z_stream zstream = { 0 } ; int zret ; zstream . next_in = ( uint8_t * ) src; zstream . avail_in = size; zstream . next_out = dst; zstream . avail_out = * len; zret = inflateInit ( & zstream ); if ( zret != Z_OK )  return zret ; zret = inflate ( & zstream , Z_SYNC_FLUSH ); return zret == Z_STREAM_END ? Z_OK : zret ; if ( ret != Z_OK )  src = zbuf; for (line = 0; line < lines; line++) if ( s -> bpp < 8 && s -> avctx -> pix_fmt == AV_PIX_FMT_PAL8 )  horizontal_fill ( s -> bpp , dst , 1 , src , 0 , width , 0 ); memcpy ( dst , src , width ); if ( is_yuv )  unpack_yuv ( s , p , dst , strip_start + line ); static void unpack_yuv(TiffContext *s, AVFrame const uint8_t *src, int lnum) int w = ( s -> width - 1 ) / s -> subsampling [ 0 ] + 1 ; uint8_t * pu = & p -> data [ 1 ] [ lnum / s -> subsampling [ 1 ] * p -> linesize [ 1 ] ] ; uint8_t * pv = & p -> data [ 2 ] [ lnum / s -> subsampling [ 1 ] * p -> linesize [ 2 ] ] ; if ( s -> width % s -> subsampling [ 0 ] || s -> height % s -> subsampling [ 1 ] )  for (i = 0; i < w; i++) for (j = 0; j < s->subsampling[1]; j++) for (k = 0; k < s->subsampling[0]; k++) p -> data [ 0 ] [ FFMIN ( lnum + j , s -> height - 1 ) * p -> linesize [ 0 ] + FFMIN ( i * s -> subsampling [ 0 ] + k , s -> width - 1 ) ] = * src ++; * pu ++ = * src ++; * pv ++ = * src ++; for (i = 0; i < w; i++) for (j = 0; j < s->subsampling[1]; j++) for (k = 0; k < s->subsampling[0]; k++) p -> data [ 0 ] [ ( lnum + j ) * p -> linesize [ 0 ] + i * s -> subsampling [ 0 ] + k ] = * src ++; * pu ++ = * src ++; * pv ++ = * src ++; line += s -> subsampling [ 1 ] - 1; dst += stride; src += width; 