Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Progressive AVIF encoding #761

Draft
wants to merge 18 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
382 changes: 358 additions & 24 deletions apps/avifenc.c

Large diffs are not rendered by default.

40 changes: 36 additions & 4 deletions include/avif/avif.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ typedef int avifBool;
#define AVIF_SPEED_SLOWEST 0
#define AVIF_SPEED_FASTEST 10

#define MAX_AV1_LAYER_COUNT 4

typedef enum avifPlanesFlag
{
AVIF_PLANES_YUV = (1 << 0),
Expand Down Expand Up @@ -151,7 +153,8 @@ typedef enum avifResult
AVIF_RESULT_WAITING_ON_IO, // similar to EAGAIN/EWOULDBLOCK, this means the avifIO doesn't have necessary data available yet
AVIF_RESULT_INVALID_ARGUMENT, // an argument passed into this function is invalid
AVIF_RESULT_NOT_IMPLEMENTED, // a requested code path is not (yet) implemented
AVIF_RESULT_OUT_OF_MEMORY
AVIF_RESULT_OUT_OF_MEMORY,
AVIF_RESULT_INVALID_LAYERS
} avifResult;

AVIF_API const char * avifResultToString(avifResult result);
Expand Down Expand Up @@ -787,9 +790,11 @@ typedef enum avifProgressiveState
// for an image sequence.
AVIF_PROGRESSIVE_STATE_UNAVAILABLE = 0,

// The current AVIF/Source offers a progressive image, but avifDecoder.allowProgressive is not
// enabled, so it will behave as if the image was not progressive and will simply decode the
// best version of this item.
// For decoder, this means the current AVIF/Source offers a progressive image, but
// avifDecoder.allowProgressive is not enabled, so it will behave as if the image was not
// progressive and will simply decode the best version of this item.
// For encoder, this means at least one of color and alpha image has multiple layers and
// indicates this is a progressive image.
AVIF_PROGRESSIVE_STATE_AVAILABLE,

// The current AVIF/Source offers a progressive image, and avifDecoder.allowProgressive is true.
Expand Down Expand Up @@ -997,6 +1002,18 @@ AVIF_API avifResult avifDecoderNthImageMaxExtent(const avifDecoder * decoder, ui
struct avifEncoderData;
struct avifCodecSpecificOptions;

typedef struct avifScalingMode {
uint64_t numerator;
uint64_t denominator;
} avifScalingMode;

typedef struct avifLayerConfig {
int minQuantizer;
int maxQuantizer;
avifScalingMode horizontalMode;
avifScalingMode verticalMode;
} avifLayerConfig;

// Notes:
// * If avifEncoderWrite() returns AVIF_RESULT_OK, output must be freed with avifRWDataFree()
// * If (maxThreads < 2), multithreading is disabled
Expand Down Expand Up @@ -1025,6 +1042,11 @@ typedef struct avifEncoder
int keyframeInterval; // How many frames between automatic forced keyframes; 0 to disable (default).
uint64_t timescale; // timescale of the media (Hz)

int extraLayerCount; // Extra layers for color sub image; 0 to disable layer image (default).
int extraLayerCountAlpha; // Extra layers for alpha sub image; 0 to disable layer image (default).
y-guyon marked this conversation as resolved.
Show resolved Hide resolved
avifLayerConfig layers[MAX_AV1_LAYER_COUNT];
avifLayerConfig layersAlpha[MAX_AV1_LAYER_COUNT];

// stats from the most recent write
avifIOStats ioStats;

Expand Down Expand Up @@ -1073,6 +1095,16 @@ AVIF_API avifResult avifEncoderAddImageGrid(avifEncoder * encoder,
uint32_t gridRows,
const avifImage * const * cellImages,
avifAddImageFlags addImageFlags);
avifResult avifEncoderAddImageProgressive(avifEncoder * encoder,
uint32_t layerCount,
const avifImage * const * layerImages,
avifAddImageFlags addImageFlags);
avifResult avifEncoderAddImageProgressiveGrid(avifEncoder * encoder,
uint32_t gridCols,
uint32_t gridRows,
uint32_t layerCount,
const avifImage * const * layerImages,
avifAddImageFlags addImageFlags);
AVIF_API avifResult avifEncoderFinish(avifEncoder * encoder, avifRWData * output);

// Codec-specific, optional "advanced" tuning settings, in the form of string key/value pairs. These
Expand Down
1 change: 1 addition & 0 deletions include/avif/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ typedef avifResult (*avifCodecEncodeImageFunc)(struct avifCodec * codec,
avifEncoder * encoder,
const avifImage * image,
avifBool alpha,
uint32_t layerIndex,
avifAddImageFlags addImageFlags,
avifCodecEncodeOutput * output);
typedef avifBool (*avifCodecEncodeFinishFunc)(struct avifCodec * codec, avifCodecEncodeOutput * output);
Expand Down
1 change: 1 addition & 0 deletions src/avif.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ const char * avifResultToString(avifResult result)
case AVIF_RESULT_INVALID_ARGUMENT: return "Invalid argument";
case AVIF_RESULT_NOT_IMPLEMENTED: return "Not implemented";
case AVIF_RESULT_OUT_OF_MEMORY: return "Out of memory";
case AVIF_RESULT_INVALID_LAYERS: return "Invalid layer image";
case AVIF_RESULT_UNKNOWN_ERROR:
default:
break;
Expand Down
Loading