func: static int encode_apng(AVCodecContext *avctx, AVPacket const AVFrame *pict, int *got_packet) PNGEncContext * s = avctx -> priv_data ; int ret ; int enc_row_size ; size_t max_packet_size ; APNGFctlChunk fctl_chunk ; if ( pict && avctx -> codec_id == AV_CODEC_ID_APNG && s -> color_type == PNG_COLOR_TYPE_PALETTE )  uint32_t checksum = ~av_crc ( av_crc_get_table ( AV_CRC_32_IEEE_LE ) , ~0U , pict -> data [ 1 ] , 256 * sizeof ( uint32_t ) ) ; if ( avctx -> frame_number == 0 )  s -> palette_checksum = checksum; if ( checksum != s -> palette_checksum )  enc_row_size = deflateBound ( & s -> zstream , ( avctx -> width * s -> bits_per_pixel + 7 ) >> 3 ); max_packet_size = AV_INPUT_BUFFER_MIN_SIZE + avctx -> height * ( enc_row_size + ( 4 + 12 ) * ( ( ( int64_t ) enc_row_size + IOBUF_SIZE - 1 ) / IOBUF_SIZE ) ); if ( max_packet_size > INT_MAX )  if ( avctx -> frame_number == 0 )  s -> bytestream = avctx -> extradata = av_malloc ( FF_MIN_BUFFER_SIZE ); if ( ! avctx -> extradata )  ret = encode_headers ( avctx , pict ); static int encode_headers(AVCodecContext *avctx, const AVFrame *pict) return 0 ; if ( ret < 0 )  avctx -> extradata_size = s -> bytestream - avctx -> extradata; s -> last_frame_packet = av_malloc ( max_packet_size ); if ( ! s -> last_frame_packet )  if ( s -> last_frame )  ret = ff_alloc_packet2 ( avctx , pkt , max_packet_size , 0 ); if ( ret < 0 )  if ( pict )  s -> bytestream_start = s -> bytestream = s -> last_frame_packet; s -> bytestream_end = s -> bytestream + max_packet_size; fctl_chunk . sequence_number = s -> sequence_number; s -> bytestream += 26 + 12; ret = apng_encode_frame ( avctx , pict , & fctl_chunk , & s -> last_frame_fctl ); static int apng_encode_frame(AVCodecContext *avctx, const AVFrame APNGFctlChunk *best_fctl_chunk, APNGFctlChunk *best_last_fctl_chunk) PNGEncContext * s = avctx -> priv_data ; int ret ; AVFrame * diffFrame ; uint8_t bpp = ( s -> bits_per_pixel + 7 ) >> 3 ; uint8_t * original_bytestream , * original_bytestream_end ; uint8_t * best_bytestream ; size_t best_bytestream_size = SIZE_MAX ; APNGFctlChunk last_fctl_chunk = * best_last_fctl_chunk ; APNGFctlChunk fctl_chunk = * best_fctl_chunk ; if ( avctx -> frame_number == 0 )  diffFrame = av_frame_alloc ( ); if ( ! diffFrame )  diffFrame -> format = pict -> format; diffFrame -> width = pict -> width; diffFrame -> height = pict -> height; if ( ( ret = av_frame_get_buffer ( diffFrame , 32 ) ) < 0 )  original_bytestream = s -> bytestream; original_bytestream_end = s -> bytestream_end; temp_bytestream = av_malloc ( original_bytestream_end - original_bytestream ); temp_bytestream_end = temp_bytestream + ( original_bytestream_end - original_bytestream ); if ( ! temp_bytestream )  for (last_fctl_chunk.dispose_op = 0; last_fctl_chunk.dispose_op < 3; ++last_fctl_chunk.dispose_op) for (fctl_chunk.blend_op = 0; fctl_chunk.blend_op < 2; ++fctl_chunk.blend_op) uint32_t original_sequence_number = s -> sequence_number , sequence_number ; uint8_t * bytestream_start = s -> bytestream ; size_t bytestream_size ; if ( last_fctl_chunk . dispose_op != APNG_DISPOSE_OP_PREVIOUS )  if ( ! s -> prev_frame )  memcpy ( diffFrame -> data [ 0 ] , s -> prev_frame -> data [ 0 ] , s -> prev_frame -> linesize [ 0 ] * s -> prev_frame -> height ); if ( apng_do_inverse_blend ( diffFrame , pict , & fctl_chunk , bpp ) < 0 )  ret = encode_frame ( avctx , diffFrame ); static int encode_frame(AVCodecContext *avctx, const AVFrame *pict) PNGEncContext * s = avctx -> priv_data ; int y , len , ret ; int row_size , pass_row_size ; row_size = ( pict -> width * s -> bits_per_pixel + 7 ) >> 3; crow_base = av_malloc ( ( row_size + 32 ) << ( s -> filter_type == PNG_FILTER_VALUE_MIXED ) ); if ( ! crow_base )  ret = AVERROR ( ENOMEM ); if ( s -> is_progressive )  progressive_buf = av_malloc ( row_size + 1 ); top_buf = av_malloc ( row_size + 1 ); if ( ! progressive_buf || ! top_buf )  ret = AVERROR ( ENOMEM ); s -> zstream . avail_out = IOBUF_SIZE; s -> zstream . next_out = s -> buf; ret = deflate ( & s -> zstream , Z_FINISH ); if ( ret == Z_OK || ret == Z_STREAM_END )  if ( ret == Z_STREAM_END )  ret = - 1; ret = 0; return ret ; s -> sequence_number = original_sequence_number; bytestream_size = s -> bytestream - bytestream_start; s -> bytestream = bytestream_start; if ( ret < 0 )  if ( bytestream_size < best_bytestream_size )  best_bytestream = s -> bytestream; best_bytestream_size = bytestream_size; if ( best_bytestream == original_bytestream )  s -> bytestream = temp_bytestream; s -> bytestream_end = temp_bytestream_end; s -> bytestream = original_bytestream; s -> bytestream_end = original_bytestream_end; static int apng_do_inverse_blend(AVFrame *output, const AVFrame APNGFctlChunk *fctl_chunk, uint8_t bpp) unsigned int x , y ; unsigned int leftmost_x = input -> width ; unsigned int rightmost_x = 0 ; unsigned int topmost_y = input -> height ; unsigned int bottommost_y = 0 ; const uint8_t * input_data = input -> data [ 0 ] ; uint8_t * output_data = output -> data [ 0 ] ; ptrdiff_t input_linesize = input -> linesize [ 0 ] ; ptrdiff_t output_linesize = output -> linesize [ 0 ] ; for (y = 0; y < input->height; ++y) for (x = 0; x < input->width; ++x) if ( ! memcmp ( input_data + bpp * x , output_data + bpp * x , bpp ) )  if ( x < leftmost_x )  leftmost_x = x; if ( x >= rightmost_x )  rightmost_x = x + 1; if ( y < topmost_y )  topmost_y = y; if ( y >= bottommost_y )  bottommost_y = y + 1; input_data += input_linesize; output_data += output_linesize; if ( leftmost_x == input -> width && rightmost_x == 0 )  leftmost_x = topmost_y = 0; rightmost_x = bottommost_y = 1; if ( fctl_chunk -> blend_op == APNG_BLEND_OP_SOURCE )  size_t transparent_palette_index ; uint32_t * palette ; switch ( input -> format )  palette = ( uint32_t * ) input -> data [ 1 ]; for (y = topmost_y; y < bottommost_y; ++y) uint8_t * foreground = input -> data [ 0 ] + input_linesize * y + bpp * leftmost_x ; uint8_t * background = output -> data [ 0 ] + output_linesize * y + bpp * leftmost_x ; output_data = output -> data [ 0 ] + output_linesize * ( y - topmost_y ); for (x = leftmost_x; x < rightmost_x; ++x, foreground += bpp, background += bpp, output_data += bpp) if ( ! memcmp ( foreground , background , bpp ) )  if ( input -> format == AV_PIX_FMT_PAL8 )  if ( transparent_palette_index == 256 )  switch ( input -> format )  if ( ( ( uint16_t * ) foreground ) [ 3 ] == 0xffff || ( ( uint16_t * ) background ) [ 3 ] == 0 )  if ( ( ( uint16_t * ) foreground ) [ 1 ] == 0xffff || ( ( uint16_t * ) background ) [ 1 ] == 0 )  if ( foreground [ 3 ] == 0xff || background [ 3 ] == 0 )  if ( foreground [ 1 ] == 0xff || background [ 1 ] == 0 )  if ( palette [ * foreground ] >> 24 == 0xff || palette [ * background ] >> 24 == 0 )  memmove ( output_data , foreground , bpp ); 