FFmpeg
Loading...
Searching...
No Matches
pngenc.c
Go to the documentation of this file.
1/*
2 * PNG image format
3 * Copyright (c) 2003 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "avcodec.h"
23#include "codec_internal.h"
24#include "encode.h"
25#include "exif_internal.h"
26#include "bytestream.h"
28#include "png.h"
29#include "apng.h"
30#include "zlib_wrapper.h"
31
32#include "libavutil/avassert.h"
33#include "libavutil/buffer.h"
34#include "libavutil/crc.h"
35#include "libavutil/csp.h"
36#include "libavutil/libm.h"
38#include "libavutil/mem.h"
39#include "libavutil/opt.h"
40#include "libavutil/pixdesc.h"
41#include "libavutil/rational.h"
42#include "libavutil/stereo3d.h"
43#include <zlib.h>
44
45#define IOBUF_SIZE 4096
46
47typedef struct APNGFctlChunk {
49 uint32_t width, height;
50 uint32_t x_offset, y_offset;
54
55typedef struct PNGEncContext {
56 AVClass *class;
58
59 uint8_t *bytestream;
62
64
66 uint8_t buf[IOBUF_SIZE];
67 int dpi; ///< Physical pixel density, in dots per inch, if set
68 int dpm; ///< Physical pixel density, in dots per meter, if set
69
74
76
77 // APNG
78 uint32_t palette_checksum; // Used to ensure a single unique palette
81 uint8_t *extra_data;
83
90
91static void png_get_interlaced_row(uint8_t *dst, int row_size,
92 int bits_per_pixel, int pass,
93 const uint8_t *src, int width)
94{
95 int x, mask, dst_x, j, b, bpp;
96 uint8_t *d;
97 const uint8_t *s;
98 static const int masks[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
99
100 mask = masks[pass];
101 switch (bits_per_pixel) {
102 case 1:
103 memset(dst, 0, row_size);
104 dst_x = 0;
105 for (x = 0; x < width; x++) {
106 j = (x & 7);
107 if ((mask << j) & 0x80) {
108 b = (src[x >> 3] >> (7 - j)) & 1;
109 dst[dst_x >> 3] |= b << (7 - (dst_x & 7));
110 dst_x++;
111 }
112 }
113 break;
114 default:
115 bpp = bits_per_pixel >> 3;
116 d = dst;
117 s = src;
118 for (x = 0; x < width; x++) {
119 j = x & 7;
120 if ((mask << j) & 0x80) {
121 memcpy(d, s, bpp);
122 d += bpp;
123 }
124 s += bpp;
125 }
126 break;
127 }
128}
129
130static void sub_png_paeth_prediction(uint8_t *dst, const uint8_t *src, const uint8_t *top,
131 int w, int bpp)
132{
133 int i;
134 for (i = 0; i < w; i++) {
135 int a, b, c, p, pa, pb, pc;
136
137 a = src[i - bpp];
138 b = top[i];
139 c = top[i - bpp];
140
141 p = b - c;
142 pc = a - c;
143
144 pa = abs(p);
145 pb = abs(pc);
146 pc = abs(p + pc);
147
148 if (pa <= pb && pa <= pc)
149 p = a;
150 else if (pb <= pc)
151 p = b;
152 else
153 p = c;
154 dst[i] = src[i] - p;
155 }
156}
157
158static void sub_left_prediction(PNGEncContext *c, uint8_t *dst, const uint8_t *src, int bpp, int size)
159{
160 const uint8_t *src1 = src + bpp;
161 const uint8_t *src2 = src;
162 int x, unaligned_w;
163
164 memcpy(dst, src, bpp);
165 dst += bpp;
166 size -= bpp;
167 unaligned_w = FFMIN(32 - bpp, size);
168 for (x = 0; x < unaligned_w; x++)
169 *dst++ = *src1++ - *src2++;
170 size -= unaligned_w;
171 c->llvidencdsp.diff_bytes(dst, src1, src2, size);
172}
173
174static void png_filter_row(PNGEncContext *c, uint8_t *dst, int filter_type,
175 const uint8_t *src, const uint8_t *top, int size, int bpp)
176{
177 int i;
178
179 switch (filter_type) {
181 memcpy(dst, src, size);
182 break;
185 break;
187 c->llvidencdsp.diff_bytes(dst, src, top, size);
188 break;
190 for (i = 0; i < bpp; i++)
191 dst[i] = src[i] - (top[i] >> 1);
192 for (; i < size; i++)
193 dst[i] = src[i] - ((src[i - bpp] + top[i]) >> 1);
194 break;
196 for (i = 0; i < bpp; i++)
197 dst[i] = src[i] - top[i];
198 sub_png_paeth_prediction(dst + i, src + i, top + i, size - i, bpp);
199 break;
200 default:
201 av_unreachable("PNG_FILTER_VALUE_MIXED can't happen here and all others are covered");
202 }
203}
204
205static uint8_t *png_choose_filter(PNGEncContext *s, uint8_t *dst,
206 const uint8_t *src, const uint8_t *top, int size, int bpp)
207{
208 int pred = s->filter_type;
209 av_assert0(bpp || !pred);
210 if (!top && pred)
213 int i;
214 int cost, bcost = INT_MAX;
215 uint8_t *buf1 = dst, *buf2 = dst + size + 16;
216 for (pred = 0; pred < 5; pred++) {
217 png_filter_row(s, buf1 + 1, pred, src, top, size, bpp);
218 buf1[0] = pred;
219 cost = 0;
220 for (i = 0; i <= size; i++)
221 cost += abs((int8_t) buf1[i]);
222 if (cost < bcost) {
223 bcost = cost;
224 FFSWAP(uint8_t *, buf1, buf2);
225 }
226 }
227 return buf2;
228 } else {
229 png_filter_row(s, dst + 1, pred, src, top, size, bpp);
230 dst[0] = pred;
231 return dst;
232 }
233}
234
235static void png_write_chunk(uint8_t **f, uint32_t tag,
236 const uint8_t *buf, int length)
237{
238 const AVCRC *crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE);
239 uint32_t crc = ~0U;
240 uint8_t tagbuf[4];
241
242 bytestream_put_be32(f, length);
243 AV_WL32(tagbuf, tag);
244 crc = av_crc(crc_table, crc, tagbuf, 4);
245 bytestream_put_be32(f, av_bswap32(tag));
246 if (length > 0) {
247 crc = av_crc(crc_table, crc, buf, length);
248 if (*f != buf)
249 memcpy(*f, buf, length);
250 *f += length;
251 }
252 bytestream_put_be32(f, ~crc);
253}
254
256 const uint8_t *buf, int length)
257{
258 PNGEncContext *s = avctx->priv_data;
259 const AVCRC *crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE);
260 uint32_t crc = ~0U;
261
262 if (avctx->codec_id == AV_CODEC_ID_PNG || avctx->frame_num == 0) {
263 png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), buf, length);
264 return;
265 }
266
267 bytestream_put_be32(&s->bytestream, length + 4);
268
269 bytestream_put_be32(&s->bytestream, MKBETAG('f', 'd', 'A', 'T'));
270 bytestream_put_be32(&s->bytestream, s->sequence_number);
271 crc = av_crc(crc_table, crc, s->bytestream - 8, 8);
272
273 crc = av_crc(crc_table, crc, buf, length);
274 memcpy(s->bytestream, buf, length);
275 s->bytestream += length;
276
277 bytestream_put_be32(&s->bytestream, ~crc);
278
279 ++s->sequence_number;
280}
281
282/* XXX: do filtering */
283static int png_write_row(AVCodecContext *avctx, const uint8_t *data, int size)
284{
285 PNGEncContext *s = avctx->priv_data;
286 z_stream *const zstream = &s->zstream.zstream;
287 int ret;
288
289 zstream->avail_in = size;
290 zstream->next_in = data;
291 while (zstream->avail_in > 0) {
292 ret = deflate(zstream, Z_NO_FLUSH);
293 if (ret != Z_OK)
294 return -1;
295 if (zstream->avail_out == 0) {
296 if (s->bytestream_end - s->bytestream > IOBUF_SIZE + 100)
297 png_write_image_data(avctx, s->buf, IOBUF_SIZE);
298 zstream->avail_out = IOBUF_SIZE;
299 zstream->next_out = s->buf;
300 }
301 }
302 return 0;
303}
304
305#define PNG_LRINT(d, divisor) lrint((d) * (divisor))
306#define PNG_Q2D(q, divisor) PNG_LRINT(av_q2d(q), (divisor))
307#define AV_WB32_PNG_D(buf, q) AV_WB32(buf, PNG_Q2D(q, 100000))
308static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf)
309{
311 if (!desc)
312 return 0;
313
314 AV_WB32_PNG_D(buf, desc->wp.x);
315 AV_WB32_PNG_D(buf + 4, desc->wp.y);
316 AV_WB32_PNG_D(buf + 8, desc->prim.r.x);
317 AV_WB32_PNG_D(buf + 12, desc->prim.r.y);
318 AV_WB32_PNG_D(buf + 16, desc->prim.g.x);
319 AV_WB32_PNG_D(buf + 20, desc->prim.g.y);
320 AV_WB32_PNG_D(buf + 24, desc->prim.b.x);
321 AV_WB32_PNG_D(buf + 28, desc->prim.b.y);
322
323 return 1;
324}
325
326static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf)
327{
328 double gamma = av_csp_approximate_eotf_gamma(trc);
329 if (gamma <= 1e-6)
330 return 0;
331
332 AV_WB32(buf, PNG_LRINT(1.0 / gamma, 100000));
333 return 1;
334}
335
337{
338 z_stream *const zstream = &s->zstream.zstream;
340 const char *name;
341 uint8_t *start, *buf;
342 int ret;
343
344 if (!sd || !sd->size)
345 return 0;
346 zstream->next_in = sd->data;
347 zstream->avail_in = sd->size;
348
349 /* write the chunk contents first */
350 start = s->bytestream + 8; /* make room for iCCP tag + length */
351 buf = start;
352
353 /* profile description */
354 entry = av_dict_get(sd->metadata, "name", NULL, 0);
355 name = (entry && entry->value[0]) ? entry->value : "icc";
356 for (int i = 0;; i++) {
357 char c = (i == 79) ? 0 : name[i];
358 bytestream_put_byte(&buf, c);
359 if (!c)
360 break;
361 }
362
363 /* compression method and profile data */
364 bytestream_put_byte(&buf, 0);
365 zstream->next_out = buf;
366 zstream->avail_out = s->bytestream_end - buf;
367 ret = deflate(zstream, Z_FINISH);
368 deflateReset(zstream);
369 if (ret != Z_STREAM_END)
370 return AVERROR_EXTERNAL;
371
372 /* rewind to the start and write the chunk header/crc */
373 png_write_chunk(&s->bytestream, MKTAG('i', 'C', 'C', 'P'), start,
374 zstream->next_out - start);
375 return 0;
376}
377
378static int encode_headers(AVCodecContext *avctx, const AVFrame *pict)
379{
380 AVFrameSideData *side_data;
381 PNGEncContext *s = avctx->priv_data;
382 int ret;
383
384 /* write png header */
385 AV_WB32(s->buf, avctx->width);
386 AV_WB32(s->buf + 4, avctx->height);
387 s->buf[8] = s->bit_depth;
388 s->buf[9] = s->color_type;
389 s->buf[10] = 0; /* compression type */
390 s->buf[11] = 0; /* filter type */
391 s->buf[12] = s->is_progressive; /* interlace type */
392 png_write_chunk(&s->bytestream, MKTAG('I', 'H', 'D', 'R'), s->buf, 13);
393
394 /* write physical information */
395 if (s->dpm) {
396 AV_WB32(s->buf, s->dpm);
397 AV_WB32(s->buf + 4, s->dpm);
398 s->buf[8] = 1; /* unit specifier is meter */
399 } else {
400 AV_WB32(s->buf, avctx->sample_aspect_ratio.num);
401 AV_WB32(s->buf + 4, avctx->sample_aspect_ratio.den);
402 s->buf[8] = 0; /* unit specifier is unknown */
403 }
404 png_write_chunk(&s->bytestream, MKTAG('p', 'H', 'Y', 's'), s->buf, 9);
405
406 /* write stereoscopic information */
408 if (side_data) {
409 AVStereo3D *stereo3d = (AVStereo3D *)side_data->data;
410 switch (stereo3d->type) {
412 s->buf[0] = ((stereo3d->flags & AV_STEREO3D_FLAG_INVERT) == 0) ? 1 : 0;
413 png_write_chunk(&s->bytestream, MKTAG('s', 'T', 'E', 'R'), s->buf, 1);
414 break;
415 case AV_STEREO3D_2D:
416 break;
417 default:
418 av_log(avctx, AV_LOG_WARNING, "Only side-by-side stereo3d flag can be defined within sTER chunk\n");
419 break;
420 }
421 }
422
423 if (s->exif_data) {
424 /* we checked for overflow when we attached the buffer to s->exif_data */
425 png_write_chunk(&s->bytestream, MKTAG('e','X','I','f'), s->exif_data->data, s->exif_data->size);
426 av_buffer_unref(&s->exif_data);
427 }
428
430 if ((ret = png_write_iccp(s, side_data)))
431 return ret;
432
433 /* write colorspace information */
434 if (pict->color_primaries == AVCOL_PRI_BT709 &&
436 s->buf[0] = 1; /* rendering intent, relative colorimetric by default */
437 png_write_chunk(&s->bytestream, MKTAG('s', 'R', 'G', 'B'), s->buf, 1);
438 } else if (pict->color_trc != AVCOL_TRC_UNSPECIFIED && !side_data) {
439 /*
440 * Avoid writing cICP if the transfer is unknown. Known primaries
441 * with unknown transfer can be handled by cHRM.
442 *
443 * We also avoid writing cICP if an ICC Profile is present, because
444 * the standard requires that cICP overrides iCCP.
445 *
446 * These values match H.273 so no translation is needed.
447 */
448 s->buf[0] = pict->color_primaries;
449 s->buf[1] = pict->color_trc;
450 s->buf[2] = 0; /* colorspace = RGB */
451 s->buf[3] = pict->color_range == AVCOL_RANGE_MPEG ? 0 : 1;
452 png_write_chunk(&s->bytestream, MKTAG('c', 'I', 'C', 'P'), s->buf, 4);
453 }
454
456 if (side_data) {
458 AV_WB32(s->buf, clli->MaxCLL * 10000);
459 AV_WB32(s->buf + 4, clli->MaxFALL * 10000);
460 png_write_chunk(&s->bytestream, MKTAG('c', 'L', 'L', 'I'), s->buf, 8);
461 }
462
464 if (side_data) {
466 if (mdcv->has_luminance && mdcv->has_primaries) {
467 for (int i = 0; i < 3; i++) {
468 AV_WB16(s->buf + 2*i, PNG_Q2D(mdcv->display_primaries[i][0], 50000));
469 AV_WB16(s->buf + 2*i + 2, PNG_Q2D(mdcv->display_primaries[i][1], 50000));
470 }
471 AV_WB16(s->buf + 12, PNG_Q2D(mdcv->white_point[0], 50000));
472 AV_WB16(s->buf + 14, PNG_Q2D(mdcv->white_point[1], 50000));
473 AV_WB32(s->buf + 16, PNG_Q2D(mdcv->max_luminance, 10000));
474 AV_WB32(s->buf + 20, PNG_Q2D(mdcv->min_luminance, 10000));
475 png_write_chunk(&s->bytestream, MKTAG('m', 'D', 'C', 'V'), s->buf, 24);
476 }
477 }
478
479 if (png_get_chrm(pict->color_primaries, s->buf))
480 png_write_chunk(&s->bytestream, MKTAG('c', 'H', 'R', 'M'), s->buf, 32);
481 if (png_get_gama(pict->color_trc, s->buf))
482 png_write_chunk(&s->bytestream, MKTAG('g', 'A', 'M', 'A'), s->buf, 4);
483
484 if (avctx->bits_per_raw_sample > 0 &&
485 avctx->bits_per_raw_sample < (s->color_type & PNG_COLOR_MASK_PALETTE ? 8 : s->bit_depth)) {
486 int len = s->color_type & PNG_COLOR_MASK_PALETTE ? 3 : ff_png_get_nb_channels(s->color_type);
487 memset(s->buf, avctx->bits_per_raw_sample, len);
488 png_write_chunk(&s->bytestream, MKTAG('s', 'B', 'I', 'T'), s->buf, len);
489 }
490
491 /* put the palette if needed, must be after colorspace information */
492 if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
493 int has_alpha, alpha, i;
494 unsigned int v;
495 uint32_t *palette;
496 uint8_t *ptr, *alpha_ptr;
497
498 palette = (uint32_t *)pict->data[1];
499 ptr = s->buf;
500 alpha_ptr = s->buf + 256 * 3;
501 has_alpha = 0;
502 for (i = 0; i < 256; i++) {
503 v = palette[i];
504 alpha = v >> 24;
505 if (alpha != 0xff)
506 has_alpha = 1;
507 *alpha_ptr++ = alpha;
508 bytestream_put_be24(&ptr, v);
509 }
510 png_write_chunk(&s->bytestream,
511 MKTAG('P', 'L', 'T', 'E'), s->buf, 256 * 3);
512 if (has_alpha) {
513 png_write_chunk(&s->bytestream,
514 MKTAG('t', 'R', 'N', 'S'), s->buf + 256 * 3, 256);
515 }
516 }
517
518 return 0;
519}
520
521static int encode_frame(AVCodecContext *avctx, const AVFrame *pict)
522{
523 PNGEncContext *s = avctx->priv_data;
524 z_stream *const zstream = &s->zstream.zstream;
525 const AVFrame *const p = pict;
526 int y, len, ret;
527 int row_size, pass_row_size;
528 uint8_t *crow_buf, *crow;
529 uint8_t *crow_base = NULL;
530 uint8_t *progressive_buf = NULL;
531 uint8_t *top_buf = NULL;
532
533 row_size = (pict->width * s->bits_per_pixel + 7) >> 3;
534
535 crow_base = av_malloc((row_size + 32) << (s->filter_type == PNG_FILTER_VALUE_MIXED));
536 if (!crow_base) {
537 ret = AVERROR(ENOMEM);
538 goto the_end;
539 }
540 // pixel data should be aligned, but there's a control byte before it
541 crow_buf = crow_base + 15;
542 if (s->is_progressive) {
543 progressive_buf = av_malloc(row_size + 1);
544 top_buf = av_malloc(row_size + 1);
545 if (!progressive_buf || !top_buf) {
546 ret = AVERROR(ENOMEM);
547 goto the_end;
548 }
549 }
550
551 /* put each row */
552 zstream->avail_out = IOBUF_SIZE;
553 zstream->next_out = s->buf;
554 if (s->is_progressive) {
555 int pass;
556
557 for (pass = 0; pass < NB_PASSES; pass++) {
558 /* NOTE: a pass is completely omitted if no pixels would be
559 * output */
560 pass_row_size = ff_png_pass_row_size(pass, s->bits_per_pixel, pict->width);
561 if (pass_row_size > 0) {
562 uint8_t *top = NULL;
563 for (y = 0; y < pict->height; y++)
564 if ((ff_png_pass_ymask[pass] << (y & 7)) & 0x80) {
565 const uint8_t *ptr = p->data[0] + y * p->linesize[0];
566 FFSWAP(uint8_t *, progressive_buf, top_buf);
567 png_get_interlaced_row(progressive_buf, pass_row_size,
568 s->bits_per_pixel, pass,
569 ptr, pict->width);
570 crow = png_choose_filter(s, crow_buf, progressive_buf,
571 top, pass_row_size, s->bits_per_pixel >> 3);
572 png_write_row(avctx, crow, pass_row_size + 1);
573 top = progressive_buf;
574 }
575 }
576 }
577 } else {
578 const uint8_t *top = NULL;
579 for (y = 0; y < pict->height; y++) {
580 const uint8_t *ptr = p->data[0] + y * p->linesize[0];
581 crow = png_choose_filter(s, crow_buf, ptr, top,
582 row_size, s->bits_per_pixel >> 3);
583 png_write_row(avctx, crow, row_size + 1);
584 top = ptr;
585 }
586 }
587 /* compress last bytes */
588 for (;;) {
589 ret = deflate(zstream, Z_FINISH);
590 if (ret == Z_OK || ret == Z_STREAM_END) {
591 len = IOBUF_SIZE - zstream->avail_out;
592 if (len > 0 && s->bytestream_end - s->bytestream > len + 100) {
593 png_write_image_data(avctx, s->buf, len);
594 }
595 zstream->avail_out = IOBUF_SIZE;
596 zstream->next_out = s->buf;
597 if (ret == Z_STREAM_END)
598 break;
599 } else {
600 ret = -1;
601 goto the_end;
602 }
603 }
604
605 ret = 0;
606
607the_end:
608 av_freep(&crow_base);
609 av_freep(&progressive_buf);
610 av_freep(&top_buf);
611 deflateReset(zstream);
612 return ret;
613}
614
615static int add_icc_profile_size(AVCodecContext *avctx, const AVFrame *pict,
616 uint64_t *max_packet_size)
617{
618 PNGEncContext *s = avctx->priv_data;
619 const AVFrameSideData *sd;
620 const int hdr_size = 128;
621 uint64_t new_pkt_size;
622 uLong bound;
623
624 if (!pict)
625 return 0;
627 if (!sd || !sd->size)
628 return 0;
629 if (sd->size != (uLong) sd->size)
630 return AVERROR_INVALIDDATA;
631
632 bound = deflateBound(&s->zstream.zstream, sd->size);
633 if (bound > INT32_MAX - hdr_size)
634 return AVERROR_INVALIDDATA;
635
636 new_pkt_size = *max_packet_size + bound + hdr_size;
637 if (new_pkt_size < *max_packet_size)
638 return AVERROR_INVALIDDATA;
639 *max_packet_size = new_pkt_size;
640 return 0;
641}
642
643static int add_exif_profile_size(AVCodecContext *avctx, const AVFrame *pict,
644 uint64_t *max_packet_size)
645{
646 uint64_t new_pkt_size;
647 PNGEncContext *s = avctx->priv_data;
648
649 int result = ff_exif_get_buffer(avctx, pict, &s->exif_data, AV_EXIF_TIFF_HEADER);
650 if (!s->exif_data) {
651 if (result < 0)
652 av_log(avctx, AV_LOG_WARNING, "unable to attach EXIF metadata: %s\n", av_err2str(result));
653 return 0;
654 }
655
656 /* png_write_chunk accepts an int, not a size_t, so we have to check overflow */
657 if (s->exif_data->size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
658 /* that's a very big exif chunk, probably a bug */
659 av_log(avctx, AV_LOG_ERROR, "extremely large EXIF buffer detected, not writing\n");
660 av_buffer_unref(&s->exif_data);
661 return 0;
662 }
663
664 /* 12 is the png chunk header size */
665 new_pkt_size = *max_packet_size + s->exif_data->size + 12;
666 if (new_pkt_size < *max_packet_size) {
667 av_buffer_unref(&s->exif_data);
668 return AVERROR_INVALIDDATA;
669 }
670
671 *max_packet_size = new_pkt_size;
672
673 return 0;
674}
675
677 const AVFrame *pict, int *got_packet)
678{
679 PNGEncContext *s = avctx->priv_data;
680 int ret;
681 int enc_row_size;
682 uint64_t max_packet_size;
683
684 enc_row_size = deflateBound(&s->zstream.zstream,
685 (avctx->width * s->bits_per_pixel + 7) >> 3);
686 max_packet_size =
687 FF_INPUT_BUFFER_MIN_SIZE + // headers
688 avctx->height * (
689 enc_row_size +
690 12 * (((int64_t)enc_row_size + IOBUF_SIZE - 1) / IOBUF_SIZE) // IDAT * ceil(enc_row_size / IOBUF_SIZE)
691 );
692 if ((ret = add_icc_profile_size(avctx, pict, &max_packet_size)))
693 return ret;
694 ret = add_exif_profile_size(avctx, pict, &max_packet_size);
695 if (ret < 0)
696 return ret;
697
698 ret = ff_alloc_packet(avctx, pkt, max_packet_size);
699 if (ret < 0)
700 return ret;
701
702 s->bytestream_start =
703 s->bytestream = pkt->data;
704 s->bytestream_end = pkt->data + pkt->size;
705
706 AV_WB64(s->bytestream, PNGSIG);
707 s->bytestream += 8;
708
709 ret = encode_headers(avctx, pict);
710 if (ret < 0)
711 return ret;
712
713 ret = encode_frame(avctx, pict);
714 if (ret < 0)
715 return ret;
716
717 png_write_chunk(&s->bytestream, MKTAG('I', 'E', 'N', 'D'), NULL, 0);
718
719 pkt->size = s->bytestream - s->bytestream_start;
720 pkt->flags |= AV_PKT_FLAG_KEY;
721 *got_packet = 1;
722
723 return 0;
724}
725
726static int apng_do_inverse_blend(AVFrame *output, const AVFrame *input,
727 APNGFctlChunk *fctl_chunk, uint8_t bpp)
728{
729 // output: background, input: foreground
730 // output the image such that when blended with the background, will produce the foreground
731
732 unsigned int x, y;
733 unsigned int leftmost_x = input->width;
734 unsigned int rightmost_x = 0;
735 unsigned int topmost_y = input->height;
736 unsigned int bottommost_y = 0;
737 const uint8_t *input_data = input->data[0];
738 uint8_t *output_data = output->data[0];
739 ptrdiff_t input_linesize = input->linesize[0];
740 ptrdiff_t output_linesize = output->linesize[0];
741
742 // Find bounding box of changes
743 for (y = 0; y < input->height; ++y) {
744 for (x = 0; x < input->width; ++x) {
745 if (!memcmp(input_data + bpp * x, output_data + bpp * x, bpp))
746 continue;
747
748 if (x < leftmost_x)
749 leftmost_x = x;
750 if (x >= rightmost_x)
751 rightmost_x = x + 1;
752 if (y < topmost_y)
753 topmost_y = y;
754 if (y >= bottommost_y)
755 bottommost_y = y + 1;
756 }
757
758 input_data += input_linesize;
759 output_data += output_linesize;
760 }
761
762 if (leftmost_x == input->width && rightmost_x == 0) {
763 // Empty frame
764 // APNG does not support empty frames, so we make it a 1x1 frame
765 leftmost_x = topmost_y = 0;
766 rightmost_x = bottommost_y = 1;
767 }
768
769 // Do actual inverse blending
770 if (fctl_chunk->blend_op == APNG_BLEND_OP_SOURCE) {
771 output_data = output->data[0];
772 for (y = topmost_y; y < bottommost_y; ++y) {
773 memcpy(output_data,
774 input->data[0] + input_linesize * y + bpp * leftmost_x,
775 bpp * (rightmost_x - leftmost_x));
776 output_data += output_linesize;
777 }
778 } else { // APNG_BLEND_OP_OVER
779 size_t transparent_palette_index;
780 uint32_t *palette;
781
782 switch (input->format) {
785 case AV_PIX_FMT_RGBA:
787 break;
788
789 case AV_PIX_FMT_PAL8:
790 palette = (uint32_t*)input->data[1];
791 for (transparent_palette_index = 0; transparent_palette_index < 256; ++transparent_palette_index)
792 if (palette[transparent_palette_index] >> 24 == 0)
793 break;
794 break;
795
796 default:
797 // No alpha, so blending not possible
798 return -1;
799 }
800
801 for (y = topmost_y; y < bottommost_y; ++y) {
802 const uint8_t *foreground = input->data[0] + input_linesize * y + bpp * leftmost_x;
803 uint8_t *background = output->data[0] + output_linesize * y + bpp * leftmost_x;
804 output_data = output->data[0] + output_linesize * (y - topmost_y);
805 for (x = leftmost_x; x < rightmost_x; ++x, foreground += bpp, background += bpp, output_data += bpp) {
806 if (!memcmp(foreground, background, bpp)) {
807 if (input->format == AV_PIX_FMT_PAL8) {
808 if (transparent_palette_index == 256) {
809 // Need fully transparent colour, but none exists
810 return -1;
811 }
812
813 *output_data = transparent_palette_index;
814 } else {
815 memset(output_data, 0, bpp);
816 }
817 continue;
818 }
819
820 // Check for special alpha values, since full inverse
821 // alpha-on-alpha blending is rarely possible, and when
822 // possible, doesn't compress much better than
823 // APNG_BLEND_OP_SOURCE blending
824 switch (input->format) {
826 if (((uint16_t*)foreground)[3] == 0xffff ||
827 ((uint16_t*)background)[3] == 0)
828 break;
829 return -1;
830
832 if (((uint16_t*)foreground)[1] == 0xffff ||
833 ((uint16_t*)background)[1] == 0)
834 break;
835 return -1;
836
837 case AV_PIX_FMT_RGBA:
838 if (foreground[3] == 0xff || background[3] == 0)
839 break;
840 return -1;
841
843 if (foreground[1] == 0xff || background[1] == 0)
844 break;
845 return -1;
846
847 case AV_PIX_FMT_PAL8:
848 if (palette[*foreground] >> 24 == 0xff ||
849 palette[*background] >> 24 == 0)
850 break;
851 return -1;
852
853 default:
854 av_unreachable("Pixfmt has been checked before");
855 }
856
857 memmove(output_data, foreground, bpp);
858 }
859 }
860 }
861
862 output->width = rightmost_x - leftmost_x;
863 output->height = bottommost_y - topmost_y;
864 fctl_chunk->width = output->width;
865 fctl_chunk->height = output->height;
866 fctl_chunk->x_offset = leftmost_x;
867 fctl_chunk->y_offset = topmost_y;
868
869 return 0;
870}
871
872static int apng_encode_frame(AVCodecContext *avctx, const AVFrame *pict,
873 APNGFctlChunk *best_fctl_chunk, APNGFctlChunk *best_last_fctl_chunk)
874{
875 PNGEncContext *s = avctx->priv_data;
876 int ret;
877 unsigned int y;
878 AVFrame* diffFrame;
879 uint8_t bpp = (s->bits_per_pixel + 7) >> 3;
880 uint8_t *original_bytestream, *original_bytestream_end;
881 uint8_t *temp_bytestream = 0, *temp_bytestream_end;
882 uint32_t best_sequence_number;
883 uint8_t *best_bytestream;
884 size_t best_bytestream_size = SIZE_MAX;
885 APNGFctlChunk last_fctl_chunk = *best_last_fctl_chunk;
886 APNGFctlChunk fctl_chunk = *best_fctl_chunk;
888
889 if (avctx->frame_num == 0) {
890 best_fctl_chunk->width = pict->width;
891 best_fctl_chunk->height = pict->height;
892 best_fctl_chunk->x_offset = 0;
893 best_fctl_chunk->y_offset = 0;
894 best_fctl_chunk->blend_op = APNG_BLEND_OP_SOURCE;
895 return encode_frame(avctx, pict);
896 }
897
898 diffFrame = av_frame_alloc();
899 if (!diffFrame)
900 return AVERROR(ENOMEM);
901
902 diffFrame->format = pict->format;
903 diffFrame->width = pict->width;
904 diffFrame->height = pict->height;
905 if ((ret = av_frame_get_buffer(diffFrame, 0)) < 0)
906 goto fail;
907
908 original_bytestream = s->bytestream;
909 original_bytestream_end = s->bytestream_end;
910
911 temp_bytestream = av_malloc(original_bytestream_end - original_bytestream);
912 if (!temp_bytestream) {
913 ret = AVERROR(ENOMEM);
914 goto fail;
915 }
916 temp_bytestream_end = temp_bytestream + (original_bytestream_end - original_bytestream);
917
918 for (last_fctl_chunk.dispose_op = 0; last_fctl_chunk.dispose_op < 3; ++last_fctl_chunk.dispose_op) {
919 // 0: APNG_DISPOSE_OP_NONE
920 // 1: APNG_DISPOSE_OP_BACKGROUND
921 // 2: APNG_DISPOSE_OP_PREVIOUS
922 if (last_fctl_chunk.dispose_op == APNG_DISPOSE_OP_BACKGROUND) {
923 if (!(desc->flags & AV_PIX_FMT_FLAG_ALPHA))
924 continue;
925 }
926 for (fctl_chunk.blend_op = 0; fctl_chunk.blend_op < 2; ++fctl_chunk.blend_op) {
927 // 0: APNG_BLEND_OP_SOURCE
928 // 1: APNG_BLEND_OP_OVER
929
930 uint32_t original_sequence_number = s->sequence_number, sequence_number;
931 uint8_t *bytestream_start = s->bytestream;
932 size_t bytestream_size;
933
934 // Do disposal
935 if (last_fctl_chunk.dispose_op != APNG_DISPOSE_OP_PREVIOUS) {
936 diffFrame->width = pict->width;
937 diffFrame->height = pict->height;
938 ret = av_frame_copy(diffFrame, s->last_frame);
939 if (ret < 0)
940 goto fail;
941
942 if (last_fctl_chunk.dispose_op == APNG_DISPOSE_OP_BACKGROUND) {
943 for (y = last_fctl_chunk.y_offset; y < last_fctl_chunk.y_offset + last_fctl_chunk.height; ++y) {
944 size_t row_start = diffFrame->linesize[0] * y + bpp * last_fctl_chunk.x_offset;
945 memset(diffFrame->data[0] + row_start, 0, bpp * last_fctl_chunk.width);
946 }
947 }
948 } else {
949 if (!s->prev_frame)
950 continue;
951
952 diffFrame->width = pict->width;
953 diffFrame->height = pict->height;
954 ret = av_frame_copy(diffFrame, s->prev_frame);
955 if (ret < 0)
956 goto fail;
957 }
958
959 // Do inverse blending
960 if (apng_do_inverse_blend(diffFrame, pict, &fctl_chunk, bpp) < 0)
961 continue;
962
963 // Do encoding
964 ret = encode_frame(avctx, diffFrame);
965 sequence_number = s->sequence_number;
966 s->sequence_number = original_sequence_number;
967 bytestream_size = s->bytestream - bytestream_start;
968 s->bytestream = bytestream_start;
969 if (ret < 0)
970 goto fail;
971
972 if (bytestream_size < best_bytestream_size) {
973 *best_fctl_chunk = fctl_chunk;
974 *best_last_fctl_chunk = last_fctl_chunk;
975
976 best_sequence_number = sequence_number;
977 best_bytestream = s->bytestream;
978 best_bytestream_size = bytestream_size;
979
980 if (best_bytestream == original_bytestream) {
981 s->bytestream = temp_bytestream;
982 s->bytestream_end = temp_bytestream_end;
983 } else {
984 s->bytestream = original_bytestream;
985 s->bytestream_end = original_bytestream_end;
986 }
987 }
988 }
989 }
990
991 s->sequence_number = best_sequence_number;
992 s->bytestream = original_bytestream + best_bytestream_size;
993 s->bytestream_end = original_bytestream_end;
994 if (best_bytestream != original_bytestream)
995 memcpy(original_bytestream, best_bytestream, best_bytestream_size);
996
997 ret = 0;
998
999fail:
1000 av_freep(&temp_bytestream);
1001 av_frame_free(&diffFrame);
1002 return ret;
1003}
1004
1006 const AVFrame *pict, int *got_packet)
1007{
1008 PNGEncContext *s = avctx->priv_data;
1009 int ret;
1010 int enc_row_size;
1011 uint64_t max_packet_size;
1012 APNGFctlChunk fctl_chunk = {0};
1013
1014 if (pict && s->color_type == PNG_COLOR_TYPE_PALETTE) {
1015 uint32_t checksum = ~av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), ~0U, pict->data[1], 256 * sizeof(uint32_t));
1016
1017 if (avctx->frame_num == 0) {
1018 s->palette_checksum = checksum;
1019 } else if (checksum != s->palette_checksum) {
1020 av_log(avctx, AV_LOG_ERROR,
1021 "Input contains more than one unique palette. APNG does not support multiple palettes.\n");
1022 return -1;
1023 }
1024 }
1025
1026 enc_row_size = deflateBound(&s->zstream.zstream,
1027 (avctx->width * s->bits_per_pixel + 7) >> 3);
1028 max_packet_size =
1029 FF_INPUT_BUFFER_MIN_SIZE + // headers
1030 avctx->height * (
1031 enc_row_size +
1032 (4 + 12) * (((int64_t)enc_row_size + IOBUF_SIZE - 1) / IOBUF_SIZE) // fdAT * ceil(enc_row_size / IOBUF_SIZE)
1033 );
1034 if (max_packet_size > INT_MAX)
1035 return AVERROR(ENOMEM);
1036
1037 if (avctx->frame_num == 0) {
1038 if (!pict)
1039 return AVERROR(EINVAL);
1040 uint64_t extradata_size = FF_INPUT_BUFFER_MIN_SIZE;
1041 ret = add_icc_profile_size(avctx, pict, &extradata_size);
1042 if (ret < 0)
1043 return ret;
1044 ret = add_exif_profile_size(avctx, pict, &extradata_size);
1045 if (ret < 0)
1046 return ret;
1047 /* the compiler will optimize this out if UINT64_MAX == SIZE_MAX */
1048 if (extradata_size > SIZE_MAX)
1049 return AVERROR(ENOMEM);
1050 s->bytestream = s->extra_data = av_malloc(extradata_size);
1051 if (!s->extra_data)
1052 return AVERROR(ENOMEM);
1053
1054 ret = encode_headers(avctx, pict);
1055 if (ret < 0)
1056 return ret;
1057
1058 s->extra_data_size = s->bytestream - s->extra_data;
1059
1060 s->last_frame_packet = av_malloc(max_packet_size);
1061 if (!s->last_frame_packet)
1062 return AVERROR(ENOMEM);
1063 } else if (s->last_frame) {
1064 ret = ff_get_encode_buffer(avctx, pkt, s->last_frame_packet_size, 0);
1065 if (ret < 0)
1066 return ret;
1067
1068 memcpy(pkt->data, s->last_frame_packet, s->last_frame_packet_size);
1069 pkt->pts = s->last_frame->pts;
1070 pkt->duration = s->last_frame->duration;
1071
1072 ret = ff_encode_reordered_opaque(avctx, pkt, s->last_frame);
1073 if (ret < 0)
1074 return ret;
1075 }
1076
1077 if (pict) {
1078 s->bytestream_start =
1079 s->bytestream = s->last_frame_packet;
1080 s->bytestream_end = s->bytestream + max_packet_size;
1081
1082 // We're encoding the frame first, so we have to do a bit of shuffling around
1083 // to have the image data write to the correct place in the buffer
1084 fctl_chunk.sequence_number = s->sequence_number;
1085 ++s->sequence_number;
1086 s->bytestream += APNG_FCTL_CHUNK_SIZE + 12;
1087
1088 ret = apng_encode_frame(avctx, pict, &fctl_chunk, &s->last_frame_fctl);
1089 if (ret < 0)
1090 return ret;
1091
1092 fctl_chunk.delay_num = 0; // delay filled in during muxing
1093 fctl_chunk.delay_den = 0;
1094 } else {
1095 s->last_frame_fctl.dispose_op = APNG_DISPOSE_OP_NONE;
1096 }
1097
1098 if (s->last_frame) {
1099 uint8_t* last_fctl_chunk_start = pkt->data;
1100 uint8_t buf[APNG_FCTL_CHUNK_SIZE];
1101 if (!s->extra_data_updated) {
1102 uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, s->extra_data_size);
1103 if (!side_data)
1104 return AVERROR(ENOMEM);
1105 memcpy(side_data, s->extra_data, s->extra_data_size);
1106 s->extra_data_updated = 1;
1107 }
1108
1109 AV_WB32(buf + 0, s->last_frame_fctl.sequence_number);
1110 AV_WB32(buf + 4, s->last_frame_fctl.width);
1111 AV_WB32(buf + 8, s->last_frame_fctl.height);
1112 AV_WB32(buf + 12, s->last_frame_fctl.x_offset);
1113 AV_WB32(buf + 16, s->last_frame_fctl.y_offset);
1114 AV_WB16(buf + 20, s->last_frame_fctl.delay_num);
1115 AV_WB16(buf + 22, s->last_frame_fctl.delay_den);
1116 buf[24] = s->last_frame_fctl.dispose_op;
1117 buf[25] = s->last_frame_fctl.blend_op;
1118 png_write_chunk(&last_fctl_chunk_start, MKTAG('f', 'c', 'T', 'L'), buf, sizeof(buf));
1119
1120 *got_packet = 1;
1121 }
1122
1123 if (pict) {
1124 if (!s->last_frame) {
1125 s->last_frame = av_frame_alloc();
1126 if (!s->last_frame)
1127 return AVERROR(ENOMEM);
1128 } else if (s->last_frame_fctl.dispose_op != APNG_DISPOSE_OP_PREVIOUS) {
1129 if (!s->prev_frame) {
1130 s->prev_frame = av_frame_alloc();
1131 if (!s->prev_frame)
1132 return AVERROR(ENOMEM);
1133
1134 s->prev_frame->format = pict->format;
1135 s->prev_frame->width = pict->width;
1136 s->prev_frame->height = pict->height;
1137 if ((ret = av_frame_get_buffer(s->prev_frame, 0)) < 0)
1138 return ret;
1139 }
1140
1141 // Do disposal, but not blending
1142 av_frame_copy(s->prev_frame, s->last_frame);
1143 if (s->last_frame_fctl.dispose_op == APNG_DISPOSE_OP_BACKGROUND) {
1144 uint32_t y;
1145 uint8_t bpp = (s->bits_per_pixel + 7) >> 3;
1146 for (y = s->last_frame_fctl.y_offset; y < s->last_frame_fctl.y_offset + s->last_frame_fctl.height; ++y) {
1147 size_t row_start = s->prev_frame->linesize[0] * y + bpp * s->last_frame_fctl.x_offset;
1148 memset(s->prev_frame->data[0] + row_start, 0, bpp * s->last_frame_fctl.width);
1149 }
1150 }
1151 }
1152
1153 ret = av_frame_replace(s->last_frame, pict);
1154 if (ret < 0)
1155 return ret;
1156
1157 s->last_frame_fctl = fctl_chunk;
1158 s->last_frame_packet_size = s->bytestream - s->bytestream_start;
1159 } else {
1160 av_frame_free(&s->last_frame);
1161 }
1162
1163 return 0;
1164}
1165
1167{
1168 PNGEncContext *s = avctx->priv_data;
1169 int compression_level;
1170
1171 switch (avctx->pix_fmt) {
1172 case AV_PIX_FMT_RGBA:
1173 avctx->bits_per_coded_sample = 32;
1174 break;
1175 case AV_PIX_FMT_RGB24:
1176 avctx->bits_per_coded_sample = 24;
1177 break;
1178 case AV_PIX_FMT_GRAY8:
1179 avctx->bits_per_coded_sample = 0x28;
1180 break;
1182 avctx->bits_per_coded_sample = 1;
1183 break;
1184 case AV_PIX_FMT_PAL8:
1185 avctx->bits_per_coded_sample = 8;
1186 }
1187
1188 ff_llvidencdsp_init(&s->llvidencdsp);
1189
1190 if (avctx->pix_fmt == AV_PIX_FMT_MONOBLACK)
1191 s->filter_type = PNG_FILTER_VALUE_NONE;
1192
1193 if (s->dpi && s->dpm) {
1194 av_log(avctx, AV_LOG_ERROR, "Only one of 'dpi' or 'dpm' options should be set\n");
1195 return AVERROR(EINVAL);
1196 } else if (s->dpi) {
1197 s->dpm = s->dpi * 10000 / 254;
1198 }
1199
1200 s->is_progressive = !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT);
1201 switch (avctx->pix_fmt) {
1203 s->bit_depth = 16;
1204 s->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1205 break;
1206 case AV_PIX_FMT_RGB48BE:
1207 s->bit_depth = 16;
1208 s->color_type = PNG_COLOR_TYPE_RGB;
1209 break;
1210 case AV_PIX_FMT_RGBA:
1211 s->bit_depth = 8;
1212 s->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1213 break;
1214 case AV_PIX_FMT_RGB24:
1215 s->bit_depth = 8;
1216 s->color_type = PNG_COLOR_TYPE_RGB;
1217 break;
1219 s->bit_depth = 16;
1220 s->color_type = PNG_COLOR_TYPE_GRAY;
1221 break;
1222 case AV_PIX_FMT_GRAY8:
1223 s->bit_depth = 8;
1224 s->color_type = PNG_COLOR_TYPE_GRAY;
1225 break;
1226 case AV_PIX_FMT_GRAY8A:
1227 s->bit_depth = 8;
1228 s->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
1229 break;
1230 case AV_PIX_FMT_YA16BE:
1231 s->bit_depth = 16;
1232 s->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
1233 break;
1235 s->bit_depth = 1;
1236 s->color_type = PNG_COLOR_TYPE_GRAY;
1237 break;
1238 case AV_PIX_FMT_PAL8:
1239 s->bit_depth = 8;
1240 s->color_type = PNG_COLOR_TYPE_PALETTE;
1241 break;
1242 default:
1243 av_unreachable("Already checked via CODEC_PIXFMTS");
1244 }
1245 s->bits_per_pixel = ff_png_get_nb_channels(s->color_type) * s->bit_depth;
1246
1247 compression_level = avctx->compression_level == FF_COMPRESSION_DEFAULT
1248 ? Z_DEFAULT_COMPRESSION
1249 : av_clip(avctx->compression_level, 0, 9);
1250 return ff_deflate_init(&s->zstream, compression_level, avctx);
1251}
1252
1254{
1255 PNGEncContext *s = avctx->priv_data;
1256
1257 ff_deflate_end(&s->zstream);
1258 av_frame_free(&s->last_frame);
1259 av_frame_free(&s->prev_frame);
1260 av_buffer_unref(&s->exif_data);
1261 av_freep(&s->last_frame_packet);
1262 av_freep(&s->extra_data);
1263 s->extra_data_size = 0;
1264 return 0;
1265}
1266
1267#define OFFSET(x) offsetof(PNGEncContext, x)
1268#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1269static const AVOption options[] = {
1270 {"dpi", "Set image resolution (in dots per inch)", OFFSET(dpi), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 0x10000, VE},
1271 {"dpm", "Set image resolution (in dots per meter)", OFFSET(dpm), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 0x10000, VE},
1272 { "pred", "Prediction method", OFFSET(filter_type), AV_OPT_TYPE_INT, { .i64 = PNG_FILTER_VALUE_PAETH }, PNG_FILTER_VALUE_NONE, PNG_FILTER_VALUE_MIXED, VE, .unit = "pred" },
1273 { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_NONE }, INT_MIN, INT_MAX, VE, .unit = "pred" },
1274 { "sub", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_SUB }, INT_MIN, INT_MAX, VE, .unit = "pred" },
1275 { "up", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_UP }, INT_MIN, INT_MAX, VE, .unit = "pred" },
1276 { "avg", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_AVG }, INT_MIN, INT_MAX, VE, .unit = "pred" },
1277 { "paeth", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_PAETH }, INT_MIN, INT_MAX, VE, .unit = "pred" },
1278 { "mixed", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PNG_FILTER_VALUE_MIXED }, INT_MIN, INT_MAX, VE, .unit = "pred" },
1279 { NULL},
1280};
1281
1282static const AVClass pngenc_class = {
1283 .class_name = "(A)PNG encoder",
1284 .item_name = av_default_item_name,
1285 .option = options,
1286 .version = LIBAVUTIL_VERSION_INT,
1287};
1288
1290 .p.name = "png",
1291 CODEC_LONG_NAME("PNG (Portable Network Graphics) image"),
1292 .p.type = AVMEDIA_TYPE_VIDEO,
1293 .p.id = AV_CODEC_ID_PNG,
1294 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
1296 .priv_data_size = sizeof(PNGEncContext),
1297 .init = png_enc_init,
1306 .alpha_modes = AVALPHA_MODE_STRAIGHT,
1307 .p.priv_class = &pngenc_class,
1308 .caps_internal = FF_CODEC_CAP_ICC_PROFILES,
1309};
1310
1312 .p.name = "apng",
1313 CODEC_LONG_NAME("APNG (Animated Portable Network Graphics) image"),
1314 .p.type = AVMEDIA_TYPE_VIDEO,
1315 .p.id = AV_CODEC_ID_APNG,
1316 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
1318 .priv_data_size = sizeof(PNGEncContext),
1319 .init = png_enc_init,
1327 .alpha_modes = AVALPHA_MODE_STRAIGHT,
1328 .p.priv_class = &pngenc_class,
1329 .caps_internal = FF_CODEC_CAP_ICC_PROFILES,
1330};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static double bound(const double threshold, const double val)
const FFCodec ff_png_encoder
Definition pngenc.c:1289
const FFCodec ff_apng_encoder
Definition pngenc.c:1311
#define VE
Definition amfenc_av1.c:30
#define entry
APNG common header.
#define APNG_FCTL_CHUNK_SIZE
Definition apng.h:42
@ APNG_DISPOSE_OP_NONE
Definition apng.h:31
@ APNG_DISPOSE_OP_BACKGROUND
Definition apng.h:32
@ APNG_DISPOSE_OP_PREVIOUS
Definition apng.h:33
@ APNG_BLEND_OP_SOURCE
Definition apng.h:37
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
#define U(x)
Definition vpx_arith.h:37
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
Definition avassert.h:109
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
Libavcodec external API header.
#define FF_COMPRESSION_DEFAULT
Definition avcodec.h:1242
refcounted data buffer API
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define f(width, name)
Definition cbs_vp8.c:236
#define s(width, name)
Definition cbs_vp9.c:198
#define CODEC_PIXFMTS(...)
#define FF_CODEC_CAP_ICC_PROFILES
Codec supports embedded ICC profiles (AV_FRAME_DATA_ICC_PROFILE).
#define FF_CODEC_ENCODE_CB(func)
#define CODEC_LONG_NAME(str)
#define av_clip
Definition common.h:100
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
Public header for CRC hash function implementation.
Colorspace value utility functions for libavutil.
#define abs(x)
static AVPacket * pkt
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size)
Check AVPacket size and allocate data.
Definition encode.c:62
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition encode.c:106
int ff_encode_reordered_opaque(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame)
Propagate user opaque values from the frame to avctx/pkt as needed.
Definition encode.c:280
#define FF_INPUT_BUFFER_MIN_SIZE
Used by some encoders as upper bound for the length of headers.
Definition encode.h:34
int ff_exif_get_buffer(void *logctx, const AVFrame *frame, AVBufferRef **buffer_ptr, enum AVExifHeaderMode header_mode)
Gets all relevant side data, collects it into an IFD, and writes it into the corresponding buffer poi...
Definition exif.c:1493
@ AV_EXIF_TIFF_HEADER
The TIFF header starts with 0x49492a00, or 0x4d4d002a.
Definition exif.h:62
EXIF metadata parser - internal functions.
#define fail
Definition test.h:479
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
Definition codec.h:147
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition codec.h:79
#define AV_CODEC_FLAG_INTERLACED_DCT
Use interlaced DCT.
Definition avcodec.h:310
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
#define AV_CODEC_CAP_FRAME_THREADS
Codec supports frame-level multithreading.
Definition codec.h:98
@ AV_CODEC_ID_PNG
Definition codec_id.h:111
@ AV_CODEC_ID_APNG
Definition codec_id.h:260
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
@ AV_PKT_DATA_NEW_EXTRADATA
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition packet.h:56
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, size_t size)
Allocate new information of a packet.
Definition packet.c:231
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
const AVCRC * av_crc_get_table(AVCRCId crc_id)
Get an initialized standard CRC table.
Definition crc.c:389
uint32_t AVCRC
Definition crc.h:46
uint32_t av_crc(const AVCRC *ctx, uint32_t crc, const uint8_t *buffer, size_t length)
Calculate the CRC of a block.
Definition crc.c:421
@ AV_CRC_32_IEEE_LE
Definition crc.h:53
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition dict.c:60
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition frame.c:659
int av_frame_replace(AVFrame *dst, const AVFrame *src)
Ensure the destination frame refers to the same data described by the source frame,...
Definition frame.c:376
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition frame.c:206
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition frame.c:711
@ AV_FRAME_DATA_CONTENT_LIGHT_LEVEL
Content light level (based on CTA-861.3).
Definition frame.h:137
@ AV_FRAME_DATA_MASTERING_DISPLAY_METADATA
Mastering display metadata associated with a video frame.
Definition frame.h:120
@ AV_FRAME_DATA_ICC_PROFILE
The data contains an ICC profile as an opaque octet buffer following the format described by ISO 1507...
Definition frame.h:144
@ AV_FRAME_DATA_STEREO3D
Stereoscopic 3d metadata.
Definition frame.h:64
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
const AVColorPrimariesDesc * av_csp_primaries_desc_from_id(enum AVColorPrimaries prm)
Retrieves a complete gamut description from an enum constant describing the color primaries.
Definition csp.c:95
double av_csp_approximate_eotf_gamma(enum AVColorTransferCharacteristic trc)
Determine a suitable EOTF 'gamma' value to match the supplied AVColorTransferCharacteristic.
Definition csp.c:187
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define AV_STEREO3D_FLAG_INVERT
Inverted views, Right/Bottom represents the left view.
Definition stereo3d.h:194
@ AV_STEREO3D_2D
Video is not stereoscopic (and metadata has to be there).
Definition stereo3d.h:52
@ AV_STEREO3D_SIDEBYSIDE
Views are next to each other.
Definition stereo3d.h:64
int a
const pixel * src2
static const int16_t alpha[]
Definition ilbcdata.h:55
#define b
Definition input.c:43
#define AV_WB32(p, v)
#define AV_WL32(p, v)
#define AV_WB64(p, v)
#define AV_WB16(p, v)
static int output_data(MLPDecodeContext *m, unsigned int substr, AVFrame *frame, int *got_frame_ptr)
Write the audio data into the output buffer.
Definition mlpdec.c:1107
const uint8_t ff_png_pass_ymask[NB_PASSES]
Definition png.c:27
int ff_png_pass_row_size(int pass, int bits_per_pixel, int width)
Definition png.c:54
int ff_png_get_nb_channels(int color_type)
Definition png.c:41
#define av_cold
Definition attributes.h:117
Stereoscopic video.
Replacements for frequently missing libm functions.
const char * desc
Definition libsvtav1.c:83
uint8_t w
Definition llvidencdsp.c:39
av_cold void ff_llvidencdsp_init(LLVidEncDSPContext *c)
static const uint16_t mask[17]
Definition lzw.c:38
#define FFSWAP(type, a, b)
Definition macros.h:52
#define FFMIN(a, b)
Definition macros.h:49
#define MKTAG(a, b, c, d)
Definition macros.h:55
#define MKBETAG(a, b, c, d)
Definition macros.h:56
Memory handling functions.
static void input_data(MLPEncodeContext *ctx, MLPSubstream *s, uint8_t **const samples, int nb_samples)
Wrapper function for inputting data in two different bit-depths.
Definition mlpenc.c:1219
uint32_t tag
Definition movenc.c:2073
const char data[16]
Definition mxf.c:149
#define av_malloc(s)
Definition ops_static.c:52
AVOptions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition pixdesc.h:147
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AVALPHA_MODE_STRAIGHT
Alpha channel is independent of color values.
Definition pixfmt.h:819
@ AV_PIX_FMT_GRAY16BE
Y , 16bpp, big-endian.
Definition pixfmt.h:104
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition pixfmt.h:75
@ AV_PIX_FMT_YA16BE
16 bits gray, 16 bits alpha (big-endian)
Definition pixfmt.h:209
@ AV_PIX_FMT_MONOBLACK
Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb.
Definition pixfmt.h:83
@ AV_PIX_FMT_GRAY8A
alias for AV_PIX_FMT_YA8
Definition pixfmt.h:143
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition pixfmt.h:81
@ AV_PIX_FMT_RGB48BE
packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big...
Definition pixfmt.h:109
@ AV_PIX_FMT_RGBA64BE
packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is st...
Definition pixfmt.h:202
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition pixfmt.h:100
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition pixfmt.h:84
AVColorPrimaries
Chromaticity coordinates of the source primaries.
Definition pixfmt.h:642
@ AVCOL_PRI_BT709
also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B
Definition pixfmt.h:644
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition pixfmt.h:672
@ AVCOL_TRC_IEC61966_2_1
IEC 61966-2-1 (sRGB or sYCC)
Definition pixfmt.h:686
@ AVCOL_TRC_UNSPECIFIED
Definition pixfmt.h:675
#define PNG_COLOR_TYPE_RGB
Definition png.h:35
#define PNG_FILTER_VALUE_MIXED
Definition png.h:45
#define PNG_COLOR_TYPE_RGB_ALPHA
Definition png.h:36
#define PNG_COLOR_TYPE_GRAY_ALPHA
Definition png.h:37
#define PNG_FILTER_VALUE_AVG
Definition png.h:43
#define PNG_COLOR_MASK_PALETTE
Definition png.h:29
#define PNGSIG
Definition png.h:49
#define PNG_FILTER_VALUE_UP
Definition png.h:42
#define PNG_COLOR_TYPE_GRAY
Definition png.h:33
#define PNG_COLOR_TYPE_PALETTE
Definition png.h:34
#define PNG_FILTER_VALUE_PAETH
Definition png.h:44
#define PNG_FILTER_VALUE_NONE
Definition png.h:40
#define PNG_FILTER_VALUE_SUB
Definition png.h:41
#define NB_PASSES
Definition png.h:47
static av_cold int png_enc_init(AVCodecContext *avctx)
Definition pngenc.c:1166
static int apng_encode_frame(AVCodecContext *avctx, const AVFrame *pict, APNGFctlChunk *best_fctl_chunk, APNGFctlChunk *best_last_fctl_chunk)
Definition pngenc.c:872
static int encode_apng(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition pngenc.c:1005
static void sub_left_prediction(PNGEncContext *c, uint8_t *dst, const uint8_t *src, int bpp, int size)
Definition pngenc.c:158
static void png_write_chunk(uint8_t **f, uint32_t tag, const uint8_t *buf, int length)
Definition pngenc.c:235
static int encode_headers(AVCodecContext *avctx, const AVFrame *pict)
Definition pngenc.c:378
static void sub_png_paeth_prediction(uint8_t *dst, const uint8_t *src, const uint8_t *top, int w, int bpp)
Definition pngenc.c:130
static int png_write_iccp(PNGEncContext *s, const AVFrameSideData *sd)
Definition pngenc.c:336
static uint8_t * png_choose_filter(PNGEncContext *s, uint8_t *dst, const uint8_t *src, const uint8_t *top, int size, int bpp)
Definition pngenc.c:205
static void png_filter_row(PNGEncContext *c, uint8_t *dst, int filter_type, const uint8_t *src, const uint8_t *top, int size, int bpp)
Definition pngenc.c:174
static int encode_png(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition pngenc.c:676
static int encode_frame(AVCodecContext *avctx, const AVFrame *pict)
Definition pngenc.c:521
static int apng_do_inverse_blend(AVFrame *output, const AVFrame *input, APNGFctlChunk *fctl_chunk, uint8_t bpp)
Definition pngenc.c:726
#define PNG_Q2D(q, divisor)
Definition pngenc.c:306
static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf)
Definition pngenc.c:308
static const AVClass pngenc_class
Definition pngenc.c:1282
static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf)
Definition pngenc.c:326
static int png_write_row(AVCodecContext *avctx, const uint8_t *data, int size)
Definition pngenc.c:283
static av_cold int png_enc_close(AVCodecContext *avctx)
Definition pngenc.c:1253
static void png_write_image_data(AVCodecContext *avctx, const uint8_t *buf, int length)
Definition pngenc.c:255
#define IOBUF_SIZE
Definition pngenc.c:45
#define OFFSET(x)
Definition pngenc.c:1267
static int add_exif_profile_size(AVCodecContext *avctx, const AVFrame *pict, uint64_t *max_packet_size)
Definition pngenc.c:643
#define PNG_LRINT(d, divisor)
Definition pngenc.c:305
static void png_get_interlaced_row(uint8_t *dst, int row_size, int bits_per_pixel, int pass, const uint8_t *src, int width)
Definition pngenc.c:91
static int add_icc_profile_size(AVCodecContext *avctx, const AVFrame *pict, uint64_t *max_packet_size)
Definition pngenc.c:615
#define AV_WB32_PNG_D(buf, q)
Definition pngenc.c:307
const char * name
Definition qsvenc.c:142
Utilities for rational number calculation.
#define av_bswap32
Definition bswap.h:47
static const float pred[4]
Definition siprdata.h:259
uint32_t x_offset
Definition pngenc.c:50
uint32_t y_offset
Definition pngenc.c:50
uint32_t width
Definition pngenc.c:49
uint16_t delay_den
Definition pngenc.c:51
uint32_t height
Definition pngenc.c:49
uint16_t delay_num
Definition pngenc.c:51
uint32_t sequence_number
Definition pngenc.c:48
uint8_t blend_op
Definition pngenc.c:52
uint8_t dispose_op
Definition pngenc.c:52
A reference to a data buffer.
Definition buffer.h:82
Describe the class of an AVClass context structure.
Definition log.h:76
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
int64_t frame_num
Frame counter, set by libavcodec.
Definition avcodec.h:1883
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel.
Definition avcodec.h:628
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition avcodec.h:1564
int bits_per_raw_sample
Bits per sample/pixel of internal libavcodec pixel/sample format.
Definition avcodec.h:1571
int compression_level
Definition avcodec.h:1241
int flags
AV_CODEC_FLAG_*.
Definition avcodec.h:500
enum AVCodecID codec_id
Definition avcodec.h:453
void * priv_data
Definition avcodec.h:470
Struct that contains both white point location and primaries location, providing the complete descrip...
Definition csp.h:78
Content light level needed by to transmit HDR over HDMI (CTA-861.3).
unsigned MaxFALL
Max average light level per frame (cd/m^2).
unsigned MaxCLL
Max content light level (cd/m^2).
Structure to hold side data for an AVFrame.
Definition frame.h:327
AVDictionary * metadata
Definition frame.h:331
size_t size
Definition frame.h:330
uint8_t * data
Definition frame.h:329
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int width
Definition frame.h:544
int height
Definition frame.h:544
enum AVColorPrimaries color_primaries
Definition frame.h:725
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition frame.h:723
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
enum AVColorTransferCharacteristic color_trc
Definition frame.h:727
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition frame.h:559
Mastering display metadata capable of representing the color volume of the display used to master the...
int has_primaries
Flag indicating whether the display primaries (and white point) are set.
AVRational max_luminance
Max luminance of mastering display (cd/m^2).
AVRational min_luminance
Min luminance of mastering display (cd/m^2).
AVRational display_primaries[3][2]
CIE 1931 xy chromaticity coords of color primaries (r, g, b order).
AVRational white_point[2]
CIE 1931 xy chromaticity coords of white point.
int has_luminance
Flag indicating whether the luminance (min_ and max_) have been set.
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
Stereo 3D type: this structure describes how two videos are packed within a single video surface,...
Definition stereo3d.h:203
enum AVStereo3DType type
How views are packed within the video.
Definition stereo3d.h:207
int flags
Additional information about the frame packing.
Definition stereo3d.h:212
int bits_per_pixel
Definition pngenc.c:73
uint32_t palette_checksum
Definition pngenc.c:78
int filter_type
Definition pngenc.c:63
FFZStream zstream
Definition pngenc.c:65
uint8_t * bytestream_end
Definition pngenc.c:61
uint8_t * last_frame_packet
Definition pngenc.c:87
AVFrame * last_frame
Definition pngenc.c:85
int bit_depth
Definition pngenc.c:71
int dpm
Physical pixel density, in dots per meter, if set.
Definition pngenc.c:68
int is_progressive
Definition pngenc.c:70
size_t last_frame_packet_size
Definition pngenc.c:88
uint8_t * bytestream
Definition pngenc.c:59
uint8_t buf[IOBUF_SIZE]
Definition pngenc.c:66
int extra_data_size
Definition pngenc.c:82
int color_type
Definition pngenc.c:72
int extra_data_updated
Definition pngenc.c:80
AVFrame * prev_frame
Definition pngenc.c:84
AVBufferRef * exif_data
Definition pngenc.c:75
int dpi
Physical pixel density, in dots per inch, if set.
Definition pngenc.c:67
uint8_t * extra_data
Definition pngenc.c:81
uint8_t * bytestream_start
Definition pngenc.c:60
APNGFctlChunk last_frame_fctl
Definition pngenc.c:86
LLVidEncDSPContext llvidencdsp
Definition pngenc.c:57
uint32_t sequence_number
Definition pngenc.c:79
#define av_freep(p)
#define av_log(a,...)
#define src1
Definition h264pred.c:141
#define src
Definition vp8dsp.c:248
#define width
Definition dsp.h:89
int size
static void deflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
int len
static double c[64]
int ff_deflate_init(FFZStream *zstream, int level, void *logctx)
Wrapper around deflateInit().
void ff_deflate_end(FFZStream *zstream)
Wrapper around deflateEnd().