Refactor read.c with avifTileInfo
diff --git a/src/read.c b/src/read.c
index d115e23..352eec6 100644
--- a/src/read.c
+++ b/src/read.c
@@ -763,17 +763,22 @@
return NULL;
}
+// A group of AVIF tiles in an image item, such as a single tile or a grid of multiple tiles.
+typedef struct avifTileInfo
+{
+ unsigned int tileCount;
+ unsigned int decodedTileCount;
+ unsigned int firstTileIndex; // Within avifDecoderData.tiles.
+ avifImageGrid grid;
+} avifTileInfo;
+
typedef struct avifDecoderData
{
avifMeta * meta; // The root-level meta box
avifTrackArray tracks;
avifTileArray tiles;
- unsigned int colorTileCount;
- unsigned int alphaTileCount;
- unsigned int decodedColorTileCount;
- unsigned int decodedAlphaTileCount;
- avifImageGrid colorGrid;
- avifImageGrid alphaGrid;
+ avifTileInfo color;
+ avifTileInfo alpha;
avifDecoderSource source;
uint8_t majorBrand[4]; // From the file's ftyp, used by AVIF_DECODER_SOURCE_AUTO
avifDiagnostics * diag; // Shallow copy; owned by avifDecoder
@@ -818,8 +823,8 @@
tile->codec = NULL;
}
}
- data->decodedColorTileCount = 0;
- data->decodedAlphaTileCount = 0;
+ data->color.decodedTileCount = 0;
+ data->alpha.decodedTileCount = 0;
}
static avifTile * avifDecoderDataCreateTile(avifDecoderData * data, uint32_t width, uint32_t height, uint8_t operatingPoint)
@@ -874,10 +879,10 @@
}
}
data->tiles.count = 0;
- data->colorTileCount = 0;
- data->alphaTileCount = 0;
- data->decodedColorTileCount = 0;
- data->decodedAlphaTileCount = 0;
+ data->color.tileCount = 0;
+ data->color.decodedTileCount = 0;
+ data->alpha.tileCount = 0;
+ data->alpha.decodedTileCount = 0;
}
static void avifDecoderDataDestroy(avifDecoderData * data)
@@ -1284,21 +1289,20 @@
// dstImage. Only the freshly decoded tiles are considered, skipping the already
// copied or not-yet-decoded tiles.
static avifBool avifDecoderDataFillImageGrid(avifDecoderData * data,
- avifImageGrid * grid,
avifImage * dstImage,
- unsigned int firstTileIndex,
+ const avifTileInfo * info,
unsigned int oldDecodedTileCount,
- unsigned int decodedTileCount,
avifBool alpha)
{
- assert(decodedTileCount > oldDecodedTileCount);
+ assert(info->decodedTileCount > oldDecodedTileCount);
+ const avifImageGrid * grid = &info->grid;
- avifTile * firstTile = &data->tiles.tile[firstTileIndex];
+ avifTile * firstTile = &data->tiles.tile[info->firstTileIndex];
avifBool firstTileUVPresent = (firstTile->image->yuvPlanes[AVIF_CHAN_U] && firstTile->image->yuvPlanes[AVIF_CHAN_V]);
// Check for tile consistency: All tiles in a grid image should match in the properties checked below.
- for (unsigned int i = AVIF_MAX(1, oldDecodedTileCount); i < decodedTileCount; ++i) {
- avifTile * tile = &data->tiles.tile[firstTileIndex + i];
+ for (unsigned int i = AVIF_MAX(1, oldDecodedTileCount); i < info->decodedTileCount; ++i) {
+ avifTile * tile = &data->tiles.tile[info->firstTileIndex + i];
avifBool uvPresent = (tile->image->yuvPlanes[AVIF_CHAN_U] && tile->image->yuvPlanes[AVIF_CHAN_V]);
if ((tile->image->width != firstTile->image->width) || (tile->image->height != firstTile->image->height) ||
(tile->image->depth != firstTile->image->depth) || (tile->image->yuvFormat != firstTile->image->yuvFormat) ||
@@ -1385,11 +1389,11 @@
avifImageSetDefaults(&dstView);
for (; rowIndex < grid->rows; ++rowIndex, colIndex = 0) {
for (; colIndex < grid->columns; ++colIndex, ++tileIndex) {
- if (tileIndex >= decodedTileCount) {
+ if (tileIndex >= info->decodedTileCount) {
// Tile is not ready yet.
return AVIF_TRUE;
}
- avifTile * tile = &data->tiles.tile[firstTileIndex + tileIndex];
+ avifTile * tile = &data->tiles.tile[info->firstTileIndex + tileIndex];
avifCropRect dstViewRect = {
firstTile->image->width * colIndex, firstTile->image->height * rowIndex, firstTile->image->width, firstTile->image->height
@@ -3390,6 +3394,29 @@
return NULL;
}
+static avifResult avifDecoderGenerateImageTiles(avifDecoder * decoder, avifTileInfo * info, avifDecoderItem * item, avifBool alpha)
+{
+ const uint32_t previousTileCount = decoder->data->tiles.count;
+ if ((info->grid.rows > 0) && (info->grid.columns > 0)) {
+ AVIF_CHECKERR(avifDecoderGenerateImageGridTiles(decoder, &info->grid, item, alpha), AVIF_RESULT_INVALID_IMAGE_GRID);
+ } else {
+ AVIF_CHECKERR(item->size != 0, AVIF_RESULT_NO_AV1_ITEMS_FOUND);
+
+ avifTile * tile = avifDecoderDataCreateTile(decoder->data, item->width, item->height, avifDecoderItemOperatingPoint(item));
+ AVIF_CHECKERR(tile, AVIF_RESULT_OUT_OF_MEMORY);
+ AVIF_CHECKERR(avifCodecDecodeInputFillFromDecoderItem(tile->input,
+ item,
+ decoder->allowProgressive,
+ decoder->imageCountLimit,
+ decoder->io->sizeHint,
+ &decoder->diag),
+ AVIF_RESULT_BMFF_PARSE_FAILED);
+ tile->input->alpha = alpha;
+ }
+ info->tileCount = decoder->data->tiles.count - previousTileCount;
+ return AVIF_RESULT_OK;
+}
+
avifResult avifDecoderReset(avifDecoder * decoder)
{
avifDiagnosticsClearError(&decoder->diag);
@@ -3400,8 +3427,8 @@
return AVIF_RESULT_OK;
}
- memset(&data->colorGrid, 0, sizeof(data->colorGrid));
- memset(&data->alphaGrid, 0, sizeof(data->alphaGrid));
+ memset(&data->color.grid, 0, sizeof(data->color.grid));
+ memset(&data->alpha.grid, 0, sizeof(data->alpha.grid));
avifDecoderDataClearTiles(data);
// Prepare / cleanup decoded image state
@@ -3518,7 +3545,7 @@
data->diag)) {
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
- data->colorTileCount = 1;
+ data->color.tileCount = 1;
if (alphaTrack) {
avifTile * alphaTile = avifDecoderDataCreateTile(data, alphaTrack->width, alphaTrack->height, 0); // No way to set operating point via tracks
@@ -3533,7 +3560,7 @@
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
alphaTile->input->alpha = AVIF_TRUE;
- data->alphaTileCount = 1;
+ data->alpha.tileCount = 1;
}
// Stash off sample table for future timing information
@@ -3541,7 +3568,7 @@
// Image sequence timing
decoder->imageIndex = -1;
- decoder->imageCount = colorTile->input->samples.count;
+ decoder->imageCount = (int)colorTile->input->samples.count;
decoder->timescale = colorTrack->mediaTimescale;
decoder->durationInTimescales = colorTrack->mediaDuration;
if (colorTrack->mediaTimescale) {
@@ -3577,7 +3604,7 @@
if (!memcmp(colorItem->type, "grid", 4)) {
avifROData readData;
AVIF_CHECKRES(avifDecoderItemRead(colorItem, decoder->io, &readData, 0, 0, data->diag));
- AVIF_CHECKERR(avifParseImageGridBox(&data->colorGrid,
+ AVIF_CHECKERR(avifParseImageGridBox(&data->color.grid,
readData.data,
readData.size,
decoder->imageSizeLimit,
@@ -3590,7 +3617,7 @@
if (alphaItem && !memcmp(alphaItem->type, "grid", 4)) {
avifROData readData;
AVIF_CHECKRES(avifDecoderItemRead(alphaItem, decoder->io, &readData, 0, 0, data->diag));
- AVIF_CHECKERR(avifParseImageGridBox(&data->alphaGrid,
+ AVIF_CHECKERR(avifParseImageGridBox(&data->alpha.grid,
readData.data,
readData.size,
decoder->imageSizeLimit,
@@ -3600,10 +3627,7 @@
}
// Find Exif and/or XMP metadata, if any
- avifResult findResult = avifDecoderFindMetadata(decoder, data->meta, decoder->image, colorItem->id);
- if (findResult != AVIF_RESULT_OK) {
- return findResult;
- }
+ AVIF_CHECKRES(avifDecoderFindMetadata(decoder, data->meta, decoder->image, colorItem->id));
// Set all counts and timing to safe-but-uninteresting values
decoder->imageIndex = -1;
@@ -3617,36 +3641,14 @@
decoder->duration = 1;
decoder->durationInTimescales = 1;
- if ((data->colorGrid.rows > 0) && (data->colorGrid.columns > 0)) {
- if (!avifDecoderGenerateImageGridTiles(decoder, &data->colorGrid, colorItem, AVIF_FALSE)) {
- return AVIF_RESULT_INVALID_IMAGE_GRID;
- }
- data->colorTileCount = data->tiles.count;
- } else {
- if (colorItem->size == 0) {
- return AVIF_RESULT_NO_AV1_ITEMS_FOUND;
- }
-
- avifTile * colorTile =
- avifDecoderDataCreateTile(data, colorItem->width, colorItem->height, avifDecoderItemOperatingPoint(colorItem));
- if (!colorTile) {
- return AVIF_RESULT_OUT_OF_MEMORY;
- }
- if (!avifCodecDecodeInputFillFromDecoderItem(colorTile->input,
- colorItem,
- decoder->allowProgressive,
- decoder->imageCountLimit,
- decoder->io->sizeHint,
- &decoder->diag)) {
- return AVIF_RESULT_BMFF_PARSE_FAILED;
- }
- data->colorTileCount = 1;
-
+ AVIF_CHECKRES(avifDecoderGenerateImageTiles(decoder, &data->color, colorItem, /*alpha=*/AVIF_FALSE));
+ if ((data->color.grid.rows == 0) || (data->color.grid.columns == 0)) {
if (colorItem->progressive) {
decoder->progressiveState = AVIF_PROGRESSIVE_STATE_AVAILABLE;
+ const avifTile * colorTile = &data->tiles.tile[0];
if (colorTile->input->samples.count > 1) {
decoder->progressiveState = AVIF_PROGRESSIVE_STATE_ACTIVE;
- decoder->imageCount = colorTile->input->samples.count;
+ decoder->imageCount = (int)colorTile->input->samples.count;
}
}
}
@@ -3658,33 +3660,7 @@
alphaItem->width = colorItem->width;
alphaItem->height = colorItem->height;
}
-
- if ((data->alphaGrid.rows > 0) && (data->alphaGrid.columns > 0)) {
- if (!avifDecoderGenerateImageGridTiles(decoder, &data->alphaGrid, alphaItem, AVIF_TRUE)) {
- return AVIF_RESULT_INVALID_IMAGE_GRID;
- }
- data->alphaTileCount = data->tiles.count - data->colorTileCount;
- } else {
- if (alphaItem->size == 0) {
- return AVIF_RESULT_NO_AV1_ITEMS_FOUND;
- }
-
- avifTile * alphaTile =
- avifDecoderDataCreateTile(data, alphaItem->width, alphaItem->height, avifDecoderItemOperatingPoint(alphaItem));
- if (!alphaTile) {
- return AVIF_RESULT_OUT_OF_MEMORY;
- }
- if (!avifCodecDecodeInputFillFromDecoderItem(alphaTile->input,
- alphaItem,
- decoder->allowProgressive,
- decoder->imageCountLimit,
- decoder->io->sizeHint,
- &decoder->diag)) {
- return AVIF_RESULT_BMFF_PARSE_FAILED;
- }
- alphaTile->input->alpha = AVIF_TRUE;
- data->alphaTileCount = 1;
- }
+ AVIF_CHECKRES(avifDecoderGenerateImageTiles(decoder, &data->alpha, alphaItem, /*alpha=*/AVIF_TRUE));
}
decoder->image->width = colorItem->width;
@@ -3692,18 +3668,15 @@
decoder->alphaPresent = (alphaItem != NULL);
decoder->image->alphaPremultiplied = decoder->alphaPresent && (colorItem->premByID == alphaItem->id);
- avifResult colorItemValidationResult = avifDecoderItemValidateAV1(colorItem, &decoder->diag, decoder->strictFlags);
- if (colorItemValidationResult != AVIF_RESULT_OK) {
- return colorItemValidationResult;
- }
+ AVIF_CHECKRES(avifDecoderItemValidateAV1(colorItem, &decoder->diag, decoder->strictFlags));
if (alphaItem) {
- avifResult alphaItemValidationResult = avifDecoderItemValidateAV1(alphaItem, &decoder->diag, decoder->strictFlags);
- if (alphaItemValidationResult != AVIF_RESULT_OK) {
- return alphaItemValidationResult;
- }
+ AVIF_CHECKRES(avifDecoderItemValidateAV1(alphaItem, &decoder->diag, decoder->strictFlags));
}
}
+ decoder->data->color.firstTileIndex = 0;
+ decoder->data->alpha.firstTileIndex = decoder->data->color.tileCount;
+
// Sanity check tiles
for (uint32_t tileIndex = 0; tileIndex < data->tiles.count; ++tileIndex) {
avifTile * tile = &data->tiles.tile[tileIndex];
@@ -3841,14 +3814,10 @@
return avifDecoderFlush(decoder);
}
-static avifResult avifDecoderPrepareTiles(avifDecoder * decoder,
- uint32_t nextImageIndex,
- unsigned int firstTileIndex,
- unsigned int tileCount,
- unsigned int decodedTileCount)
+static avifResult avifDecoderPrepareTiles(avifDecoder * decoder, uint32_t nextImageIndex, const avifTileInfo * info)
{
- for (unsigned int tileIndex = decodedTileCount; tileIndex < tileCount; ++tileIndex) {
- avifTile * tile = &decoder->data->tiles.tile[firstTileIndex + tileIndex];
+ for (unsigned int tileIndex = info->decodedTileCount; tileIndex < info->tileCount; ++tileIndex) {
+ avifTile * tile = &decoder->data->tiles.tile[info->firstTileIndex + tileIndex];
// Ensure there's an AV1 codec available before doing anything else
if (!tile->codec) {
@@ -3910,15 +3879,11 @@
return AVIF_RESULT_OK;
}
-static avifResult avifDecoderDecodeTiles(avifDecoder * decoder,
- uint32_t nextImageIndex,
- unsigned int firstTileIndex,
- unsigned int tileCount,
- unsigned int * decodedTileCount)
+static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextImageIndex, avifTileInfo * info)
{
- const unsigned int oldDecodedTileCount = *decodedTileCount;
- for (unsigned int tileIndex = oldDecodedTileCount; tileIndex < tileCount; ++tileIndex) {
- avifTile * tile = &decoder->data->tiles.tile[firstTileIndex + tileIndex];
+ const unsigned int oldDecodedTileCount = info->decodedTileCount;
+ for (unsigned int tileIndex = oldDecodedTileCount; tileIndex < info->tileCount; ++tileIndex) {
+ avifTile * tile = &decoder->data->tiles.tile[info->firstTileIndex + tileIndex];
const avifDecodeSample * sample = &tile->input->samples.sample[nextImageIndex];
if (sample->data.size < sample->size) {
@@ -3958,11 +3923,56 @@
}
}
- ++*decodedTileCount;
+ ++info->decodedTileCount;
}
return AVIF_RESULT_OK;
}
+avifResult avifDecoderOutputDecodedTiles(avifDecoder * decoder, const avifTileInfo * info, avifBool alpha, unsigned int oldDecodedTileCount)
+{
+ if (info->decodedTileCount == oldDecodedTileCount) {
+ // Nothing changed.
+ return AVIF_RESULT_OK;
+ }
+ // There is at least one newly decoded tile.
+ assert(info->decodedTileCount > oldDecodedTileCount);
+
+ // Grid path.
+ if ((info->grid.rows > 0) && (info->grid.columns > 0)) {
+ assert(info->tileCount == (info->grid.rows * info->grid.columns));
+ AVIF_CHECKERR(avifDecoderDataFillImageGrid(decoder->data, decoder->image, info, oldDecodedTileCount, alpha),
+ AVIF_RESULT_INVALID_IMAGE_GRID);
+ return AVIF_RESULT_OK;
+ }
+
+ // Normal (most common) non-grid path. Just steal the planes from the only "tile".
+ assert(info->tileCount == 1);
+ avifImage * src = decoder->data->tiles.tile[info->firstTileIndex].image;
+ if ((decoder->image->width != src->width) || (decoder->image->height != src->height) || (decoder->image->depth != src->depth)) {
+ if (alpha) {
+ avifDiagnosticsPrintf(&decoder->diag,
+ "The color image item does not match the alpha image item in width, height, or bit depth");
+ return AVIF_RESULT_DECODE_ALPHA_FAILED;
+ }
+ avifImageFreePlanes(decoder->image, AVIF_PLANES_ALL);
+
+ decoder->image->width = src->width;
+ decoder->image->height = src->height;
+ decoder->image->depth = src->depth;
+ }
+#if 0
+ // This code is currently unnecessary as the CICP is always set by the end of avifDecoderParse().
+ if (!alpha && !decoder->data->cicpSet) {
+ decoder->data->cicpSet = AVIF_TRUE;
+ decoder->image->colorPrimaries = src->colorPrimaries;
+ decoder->image->transferCharacteristics = src->transferCharacteristics;
+ decoder->image->matrixCoefficients = src->matrixCoefficients;
+ }
+#endif
+ avifImageStealPlanes(decoder->image, src, alpha ? AVIF_PLANES_A : AVIF_PLANES_YUV);
+ return AVIF_RESULT_OK;
+}
+
avifResult avifDecoderNextImage(avifDecoder * decoder)
{
avifDiagnosticsClearError(&decoder->diag);
@@ -3976,128 +3986,48 @@
return AVIF_RESULT_IO_NOT_SET;
}
- if ((decoder->data->decodedColorTileCount == decoder->data->colorTileCount) &&
- (decoder->data->decodedAlphaTileCount == decoder->data->alphaTileCount)) {
+ if ((decoder->data->color.decodedTileCount == decoder->data->color.tileCount) &&
+ (decoder->data->alpha.decodedTileCount == decoder->data->alpha.tileCount)) {
// A frame was decoded during the last avifDecoderNextImage() call.
- decoder->data->decodedColorTileCount = 0;
- decoder->data->decodedAlphaTileCount = 0;
+ decoder->data->color.decodedTileCount = 0;
+ decoder->data->alpha.decodedTileCount = 0;
}
- assert(decoder->data->tiles.count == (decoder->data->colorTileCount + decoder->data->alphaTileCount));
+ assert(decoder->data->tiles.count == (decoder->data->color.tileCount + decoder->data->alpha.tileCount));
const uint32_t nextImageIndex = (uint32_t)(decoder->imageIndex + 1);
- const unsigned int firstColorTileIndex = 0;
- const unsigned int firstAlphaTileIndex = decoder->data->colorTileCount;
// Acquire all sample data for the current image first, allowing for any read call to bail out
// with AVIF_RESULT_WAITING_ON_IO harmlessly / idempotently, unless decoder->allowIncremental.
// Start with color tiles.
- const avifResult prepareColorTileResult =
- avifDecoderPrepareTiles(decoder, nextImageIndex, firstColorTileIndex, decoder->data->colorTileCount, decoder->data->decodedColorTileCount);
- if ((prepareColorTileResult != AVIF_RESULT_OK) &&
- (!decoder->allowIncremental || (prepareColorTileResult != AVIF_RESULT_WAITING_ON_IO))) {
- return prepareColorTileResult;
+ const avifResult prepareColorTileResult = avifDecoderPrepareTiles(decoder, nextImageIndex, &decoder->data->color);
+ if (!decoder->allowIncremental || (prepareColorTileResult != AVIF_RESULT_WAITING_ON_IO)) {
+ AVIF_CHECKRES(prepareColorTileResult);
}
// Do the same with alpha tiles. They are handled separately because their
// order of appearance relative to the color tiles in the bitstream is left
// to the encoder's choice, and decoding as many as possible of each
// category in parallel is beneficial for incremental decoding, as pixel
// rows need all channels to be decoded before being accessible to the user.
- const avifResult prepareAlphaTileResult =
- avifDecoderPrepareTiles(decoder, nextImageIndex, firstAlphaTileIndex, decoder->data->alphaTileCount, decoder->data->decodedAlphaTileCount);
- if ((prepareAlphaTileResult != AVIF_RESULT_OK) &&
- (!decoder->allowIncremental || (prepareAlphaTileResult != AVIF_RESULT_WAITING_ON_IO))) {
- return prepareAlphaTileResult;
+ const avifResult prepareAlphaTileResult = avifDecoderPrepareTiles(decoder, nextImageIndex, &decoder->data->alpha);
+ if (!decoder->allowIncremental || (prepareAlphaTileResult != AVIF_RESULT_WAITING_ON_IO)) {
+ AVIF_CHECKRES(prepareAlphaTileResult);
}
// Decode all available color tiles now, then all available alpha tiles.
- const unsigned int oldDecodedColorTileCount = decoder->data->decodedColorTileCount;
- const avifResult decodeColorTileResult =
- avifDecoderDecodeTiles(decoder, nextImageIndex, firstColorTileIndex, decoder->data->colorTileCount, &decoder->data->decodedColorTileCount);
- if (decodeColorTileResult != AVIF_RESULT_OK) {
- return decodeColorTileResult;
- }
- const unsigned int oldDecodedAlphaTileCount = decoder->data->decodedAlphaTileCount;
- const avifResult decodeAlphaTileResult =
- avifDecoderDecodeTiles(decoder, nextImageIndex, firstAlphaTileIndex, decoder->data->alphaTileCount, &decoder->data->decodedAlphaTileCount);
- if (decodeAlphaTileResult != AVIF_RESULT_OK) {
- return decodeAlphaTileResult;
- }
+ const unsigned int oldDecodedColorTileCount = decoder->data->color.decodedTileCount;
+ const unsigned int oldDecodedAlphaTileCount = decoder->data->alpha.decodedTileCount;
+ AVIF_CHECKRES(avifDecoderDecodeTiles(decoder, nextImageIndex, &decoder->data->color));
+ AVIF_CHECKRES(avifDecoderDecodeTiles(decoder, nextImageIndex, &decoder->data->alpha));
- if (decoder->data->decodedColorTileCount > oldDecodedColorTileCount) {
- // There is at least one newly decoded color tile.
- if ((decoder->data->colorGrid.rows > 0) && (decoder->data->colorGrid.columns > 0)) {
- assert(decoder->data->colorTileCount == (decoder->data->colorGrid.rows * decoder->data->colorGrid.columns));
- if (!avifDecoderDataFillImageGrid(decoder->data,
- &decoder->data->colorGrid,
- decoder->image,
- firstColorTileIndex,
- oldDecodedColorTileCount,
- decoder->data->decodedColorTileCount,
- AVIF_FALSE)) {
- return AVIF_RESULT_INVALID_IMAGE_GRID;
- }
- } else {
- // Normal (most common) non-grid path. Just steal the planes from the only "tile".
- assert(decoder->data->colorTileCount == 1);
- avifImage * srcColor = decoder->data->tiles.tile[0].image;
- if ((decoder->image->width != srcColor->width) || (decoder->image->height != srcColor->height) ||
- (decoder->image->depth != srcColor->depth)) {
- avifImageFreePlanes(decoder->image, AVIF_PLANES_ALL);
+ AVIF_CHECKRES(avifDecoderOutputDecodedTiles(decoder, &decoder->data->color, /*alpha=*/AVIF_FALSE, oldDecodedColorTileCount));
+ AVIF_CHECKRES(avifDecoderOutputDecodedTiles(decoder, &decoder->data->alpha, /*alpha=*/AVIF_TRUE, oldDecodedAlphaTileCount));
- decoder->image->width = srcColor->width;
- decoder->image->height = srcColor->height;
- decoder->image->depth = srcColor->depth;
- }
-
-#if 0
- // This code is currently unnecessary as the CICP is always set by the end of avifDecoderParse().
- if (!decoder->data->cicpSet) {
- decoder->data->cicpSet = AVIF_TRUE;
- decoder->image->colorPrimaries = srcColor->colorPrimaries;
- decoder->image->transferCharacteristics = srcColor->transferCharacteristics;
- decoder->image->matrixCoefficients = srcColor->matrixCoefficients;
- }
-#endif
-
- avifImageStealPlanes(decoder->image, srcColor, AVIF_PLANES_YUV);
- }
- }
-
- if (decoder->data->decodedAlphaTileCount > oldDecodedAlphaTileCount) {
- // There is at least one newly decoded alpha tile.
- if ((decoder->data->alphaGrid.rows > 0) && (decoder->data->alphaGrid.columns > 0)) {
- assert(decoder->data->alphaTileCount == (decoder->data->alphaGrid.rows * decoder->data->alphaGrid.columns));
- if (!avifDecoderDataFillImageGrid(decoder->data,
- &decoder->data->alphaGrid,
- decoder->image,
- firstAlphaTileIndex,
- oldDecodedAlphaTileCount,
- decoder->data->decodedAlphaTileCount,
- AVIF_TRUE)) {
- return AVIF_RESULT_INVALID_IMAGE_GRID;
- }
- } else {
- // Normal (most common) non-grid path. Just steal the planes from the only "tile".
- assert(decoder->data->alphaTileCount == 1);
- avifImage * srcAlpha = decoder->data->tiles.tile[decoder->data->colorTileCount].image;
- if ((decoder->image->width != srcAlpha->width) || (decoder->image->height != srcAlpha->height) ||
- (decoder->image->depth != srcAlpha->depth)) {
- avifDiagnosticsPrintf(&decoder->diag, "decoder->image does not match srcAlpha in width, height, or bit depth");
- return AVIF_RESULT_DECODE_ALPHA_FAILED;
- }
-
- avifImageStealPlanes(decoder->image, srcAlpha, AVIF_PLANES_A);
- }
- }
-
- if ((decoder->data->decodedColorTileCount != decoder->data->colorTileCount) ||
- (decoder->data->decodedAlphaTileCount != decoder->data->alphaTileCount)) {
+ if ((decoder->data->color.decodedTileCount != decoder->data->color.tileCount) ||
+ (decoder->data->alpha.decodedTileCount != decoder->data->alpha.tileCount)) {
assert(decoder->allowIncremental);
// The image is not completely decoded. There should be no error unrelated to missing bytes,
// and at least some missing bytes.
- assert((prepareColorTileResult == AVIF_RESULT_OK) || (prepareColorTileResult == AVIF_RESULT_WAITING_ON_IO));
- assert((prepareAlphaTileResult == AVIF_RESULT_OK) || (prepareAlphaTileResult == AVIF_RESULT_WAITING_ON_IO));
- assert((prepareColorTileResult != AVIF_RESULT_OK) || (prepareAlphaTileResult != AVIF_RESULT_OK));
+ assert((prepareColorTileResult == AVIF_RESULT_WAITING_ON_IO) || (prepareAlphaTileResult == AVIF_RESULT_WAITING_ON_IO));
// Return the "not enough bytes" status now instead of moving on to the next frame.
return AVIF_RESULT_WAITING_ON_IO;
}
@@ -4106,7 +4036,7 @@
// Only advance decoder->imageIndex once the image is completely decoded, so that
// avifDecoderNthImage(decoder, decoder->imageIndex + 1) is equivalent to avifDecoderNextImage(decoder)
// if the previous call to avifDecoderNextImage() returned AVIF_RESULT_WAITING_ON_IO.
- decoder->imageIndex = nextImageIndex;
+ decoder->imageIndex = (int)nextImageIndex;
// The decoded tile counts will be reset to 0 the next time avifDecoderNextImage() is called,
// for avifDecoderDecodedRowCount() to work until then.
if (decoder->data->sourceSampleTable) {
@@ -4177,8 +4107,8 @@
}
if (requestedIndex == decoder->imageIndex) {
- if ((decoder->data->decodedColorTileCount == decoder->data->colorTileCount) &&
- (decoder->data->decodedAlphaTileCount == decoder->data->alphaTileCount)) {
+ if ((decoder->data->color.decodedTileCount == decoder->data->color.tileCount) &&
+ (decoder->data->alpha.decodedTileCount == decoder->data->alpha.tileCount)) {
// The current fully decoded image (decoder->imageIndex) is requested, nothing to do
return AVIF_RESULT_OK;
}
@@ -4242,23 +4172,19 @@
}
// Returns the number of available rows in decoder->image given a color or alpha subimage.
-static uint32_t avifGetDecodedRowCount(const avifDecoder * decoder,
- const avifImageGrid * grid,
- unsigned int firstTileIndex,
- unsigned int tileCount,
- unsigned int decodedTileCount)
+static uint32_t avifGetDecodedRowCount(const avifDecoder * decoder, const avifTileInfo * info)
{
- if (decodedTileCount == tileCount) {
+ if (info->decodedTileCount == info->tileCount) {
return decoder->image->height;
}
- if (decodedTileCount == 0) {
+ if (info->decodedTileCount == 0) {
return 0;
}
- if ((grid->rows > 0) && (grid->columns > 0)) {
+ if ((info->grid.rows > 0) && (info->grid.columns > 0)) {
// Grid of AVIF tiles (not to be confused with AV1 tiles).
- const uint32_t tileHeight = decoder->data->tiles.tile[firstTileIndex].height;
- return AVIF_MIN((decodedTileCount / grid->columns) * tileHeight, decoder->image->height);
+ const uint32_t tileHeight = decoder->data->tiles.tile[info->firstTileIndex].height;
+ return AVIF_MIN((info->decodedTileCount / info->grid.columns) * tileHeight, decoder->image->height);
} else {
// Non-grid image.
return decoder->image->height;
@@ -4267,16 +4193,11 @@
uint32_t avifDecoderDecodedRowCount(const avifDecoder * decoder)
{
- const uint32_t colorRowCount = avifGetDecodedRowCount(decoder,
- &decoder->data->colorGrid,
- /*firstTileIndex=*/0,
- decoder->data->colorTileCount,
- decoder->data->decodedColorTileCount);
- const uint32_t alphaRowCount = avifGetDecodedRowCount(decoder,
- &decoder->data->alphaGrid,
- /*firstTileIndex=*/decoder->data->colorTileCount,
- decoder->data->alphaTileCount,
- decoder->data->decodedAlphaTileCount);
+ const uint32_t colorRowCount = avifGetDecodedRowCount(decoder, &decoder->data->color);
+ if (colorRowCount == 0) {
+ return 0;
+ }
+ const uint32_t alphaRowCount = avifGetDecodedRowCount(decoder, &decoder->data->alpha);
return AVIF_MIN(colorRowCount, alphaRowCount);
}