Replace some assertions by AVIF_ASSERT_OR_RETURN() (#1958)
Add CHANGELOG.md entry
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f31161d..71cc78a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,6 +45,7 @@
* Add avif_cxx.h as a C++ header with basic functionality.
* Add enum aliases AVIF_COLOR_PRIMARIES_SRGB, AVIF_COLOR_PRIMARIES_BT2100,
AVIF_COLOR_PRIMARIES_DCI_P3, AVIF_TRANSFER_CHARACTERISTICS_PQ.
+* Add avifResult enum entry AVIF_RESULT_INTERNAL_ERROR.
### Changed
* Update aom.cmd: v3.8.1
diff --git a/include/avif/avif.h b/include/avif/avif.h
index ef63353..e9cb1de 100644
--- a/include/avif/avif.h
+++ b/include/avif/avif.h
@@ -186,10 +186,11 @@
AVIF_RESULT_OUT_OF_MEMORY = 26,
AVIF_RESULT_CANNOT_CHANGE_SETTING = 27, // a setting that can't change is changed during encoding
AVIF_RESULT_INCOMPATIBLE_IMAGE = 28, // the image is incompatible with already encoded images
+ AVIF_RESULT_INTERNAL_ERROR = 29, // some invariants have not been satisfied (likely a bug in libavif)
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
- AVIF_RESULT_ENCODE_GAIN_MAP_FAILED = 29,
- AVIF_RESULT_DECODE_GAIN_MAP_FAILED = 30,
- AVIF_RESULT_INVALID_TONE_MAPPED_IMAGE = 31,
+ AVIF_RESULT_ENCODE_GAIN_MAP_FAILED = 30,
+ AVIF_RESULT_DECODE_GAIN_MAP_FAILED = 31,
+ AVIF_RESULT_INVALID_TONE_MAPPED_IMAGE = 32,
#endif
// Kept for backward compatibility; please use the symbols above instead.
diff --git a/include/avif/internal.h b/include/avif/internal.h
index 7e0396b..3cf3aa0 100644
--- a/include/avif/internal.h
+++ b/include/avif/internal.h
@@ -59,6 +59,13 @@
} \
} while (0)
+// AVIF_ASSERT_OR_RETURN() can be used instead of assert() for extra security in release builds.
+#ifdef NDEBUG
+#define AVIF_ASSERT_OR_RETURN(A) AVIF_CHECKERR((A), AVIF_RESULT_INTERNAL_ERROR)
+#else
+#define AVIF_ASSERT_OR_RETURN(A) assert(A)
+#endif
+
// ---------------------------------------------------------------------------
// URNs and Content-Types
diff --git a/src/avif.c b/src/avif.c
index 5d6609c..264d004 100644
--- a/src/avif.c
+++ b/src/avif.c
@@ -103,6 +103,7 @@
case AVIF_RESULT_OUT_OF_MEMORY: return "Out of memory";
case AVIF_RESULT_CANNOT_CHANGE_SETTING: return "Cannot change some setting during encoding";
case AVIF_RESULT_INCOMPATIBLE_IMAGE: return "The image is incompatible with already encoded images";
+ case AVIF_RESULT_INTERNAL_ERROR: return "Internal error";
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
case AVIF_RESULT_ENCODE_GAIN_MAP_FAILED: return "Encoding of gain map planes failed";
case AVIF_RESULT_DECODE_GAIN_MAP_FAILED: return "Decoding of gain map planes failed";
diff --git a/src/read.c b/src/read.c
index 43e8687..7e24828 100644
--- a/src/read.c
+++ b/src/read.c
@@ -566,7 +566,7 @@
}
}
if (remainingSize > 0) {
- assert(layerCount == 3);
+ AVIF_ASSERT_OR_RETURN(layerCount == 3);
++layerCount;
layerSizes[3] = remainingSize;
}
@@ -611,7 +611,7 @@
sample->itemID = item->id;
sample->offset = 0;
sample->size = sampleSize;
- assert(lselProp->u.lsel.layerID < AVIF_MAX_AV1_LAYER_COUNT);
+ AVIF_ASSERT_OR_RETURN(lselProp->u.lsel.layerID < AVIF_MAX_AV1_LAYER_COUNT);
sample->spatialID = (uint8_t)lselProp->u.lsel.layerID;
sample->sync = AVIF_TRUE;
} else if (allowProgressive && item->progressive) {
@@ -790,7 +790,7 @@
static avifResult avifMetaFindOrCreateItem(avifMeta * meta, uint32_t itemID, avifDecoderItem ** item, avifDiagnostics * diag)
{
*item = NULL;
- assert(itemID != 0);
+ AVIF_ASSERT_OR_RETURN(itemID != 0);
for (uint32_t i = 0; i < meta->items.count; ++i) {
if (meta->items.item[i]->id == itemID) {
@@ -1055,7 +1055,7 @@
size_t remainingBytes = sample->size; // This may be smaller than item->size if the item is progressive
// Assert that the for loop below will execute at least one iteration.
- assert(item->extents.count != 0);
+ AVIF_ASSERT_OR_RETURN(item->extents.count != 0);
uint64_t minOffset = UINT64_MAX;
uint64_t maxOffset = 0;
for (uint32_t extentIter = 0; extentIter < item->extents.count; ++extentIter) {
@@ -1380,8 +1380,8 @@
memcpy(&item->mergedExtents, &offsetBuffer, sizeof(avifRWData));
item->mergedExtents.size = bytesToRead;
} else {
- assert(item->ownsMergedExtents);
- assert(front);
+ AVIF_ASSERT_OR_RETURN(item->ownsMergedExtents);
+ AVIF_ASSERT_OR_RETURN(front);
memcpy(front, offsetBuffer.data, bytesToRead);
front += bytesToRead;
}
@@ -1526,7 +1526,7 @@
avifBool alpha = (tile->input->itemCategory == AVIF_ITEM_ALPHA);
if (alpha) {
// An alpha tile does not contain any YUV pixels.
- assert(tile->image->yuvFormat == AVIF_PIXEL_FORMAT_NONE);
+ AVIF_ASSERT_OR_RETURN(tile->image->yuvFormat == AVIF_PIXEL_FORMAT_NONE);
}
if (!avifAreGridDimensionsValid(tile->image->yuvFormat, grid->outputWidth, grid->outputHeight, tile->image->width, tile->image->height, data->diag)) {
return AVIF_RESULT_INVALID_IMAGE_GRID;
@@ -1573,11 +1573,11 @@
// After verifying that the relevant properties of the tile match those of the first tile, copies over the pixels from the tile
// into dstImage.
-static avifBool avifDecoderDataCopyTileToImage(avifDecoderData * data,
- const avifTileInfo * info,
- avifImage * dstImage,
- const avifTile * tile,
- unsigned int tileIndex)
+static avifResult avifDecoderDataCopyTileToImage(avifDecoderData * data,
+ const avifTileInfo * info,
+ avifImage * dstImage,
+ const avifTile * tile,
+ unsigned int tileIndex)
{
const avifImageGrid * grid = &info->grid;
const avifTile * firstTile = &data->tiles.tile[info->firstTileIndex];
@@ -1589,7 +1589,7 @@
(tile->image->transferCharacteristics != firstTile->image->transferCharacteristics) ||
(tile->image->matrixCoefficients != firstTile->image->matrixCoefficients)) {
avifDiagnosticsPrintf(data->diag, "Grid image contains mismatched tiles");
- return AVIF_FALSE;
+ return AVIF_RESULT_INVALID_IMAGE_GRID;
}
}
@@ -1612,18 +1612,15 @@
avifImage * dst = dstImage;
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) {
- assert(dst->gainMap && dst->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(dst->gainMap && dst->gainMap->image);
dst = dst->gainMap->image;
}
#endif
- if ((avifImageSetViewRect(&dstView, dst, &dstViewRect) != AVIF_RESULT_OK) ||
- (avifImageSetViewRect(&srcView, tile->image, &srcViewRect) != AVIF_RESULT_OK)) {
- assert(AVIF_FALSE);
- return AVIF_FALSE;
- }
+ AVIF_ASSERT_OR_RETURN(avifImageSetViewRect(&dstView, dst, &dstViewRect) == AVIF_RESULT_OK &&
+ avifImageSetViewRect(&srcView, tile->image, &srcViewRect) == AVIF_RESULT_OK);
avifImageCopySamples(&dstView, &srcView, (tile->input->itemCategory == AVIF_ITEM_ALPHA) ? AVIF_PLANES_A : AVIF_PLANES_YUV);
- return AVIF_TRUE;
+ return AVIF_RESULT_OK;
}
// If colorId == 0 (a sentinel value as item IDs must be nonzero), accept any found EXIF/XMP metadata. Passing in 0
@@ -1927,7 +1924,7 @@
uint8_t flags;
AVIF_CHECK(avifROStreamRead(&s, &flags, 1)); // unsigned int(8) flags;
uint8_t channelCount = (flags & 1) * 2 + 1;
- assert(channelCount == 1 || channelCount == 3);
+ AVIF_ASSERT_OR_RETURN(channelCount == 1 || channelCount == 3);
metadata->useBaseColorSpace = (flags & 2) != 0;
metadata->backwardDirection = (flags & 4) != 0;
const avifBool useCommonDenominator = (flags & 8) != 0;
@@ -2025,13 +2022,13 @@
} else {
// item was generated for convenience and is not part of the bitstream.
// grid information should already be set.
- assert(grid->rows > 0 && grid->columns > 0);
+ AVIF_ASSERT_OR_RETURN(grid->rows > 0 && grid->columns > 0);
}
*codecType = avifDecoderItemGetGridCodecType(item);
AVIF_CHECKERR(*codecType != AVIF_CODEC_TYPE_UNKNOWN, AVIF_RESULT_INVALID_IMAGE_GRID);
} else {
*codecType = avifGetCodecType(item->type);
- assert(*codecType != AVIF_CODEC_TYPE_UNKNOWN);
+ AVIF_ASSERT_OR_RETURN(*codecType != AVIF_CODEC_TYPE_UNKNOWN);
}
return AVIF_RESULT_OK;
}
@@ -2356,7 +2353,7 @@
if (meta->fromMini) {
// The CondensedImageBox will always create 8 item properties, so to refer to the
// first property in the ItemPropertyContainerBox of its extendedMeta field, use index 9.
- assert(meta->properties.count >= 8);
+ AVIF_ASSERT_OR_RETURN(meta->properties.count >= 8);
}
#endif // AVIF_ENABLE_EXPERIMENTAL_AVIR
@@ -2643,7 +2640,7 @@
AVIF_CHECKERR(avifROStreamReadU16(&s, &tmp), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(16) item_ID;
itemID = tmp;
} else {
- assert(version == 3);
+ AVIF_ASSERT_OR_RETURN(version == 3);
AVIF_CHECKERR(avifROStreamReadU32(&s, &itemID), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(32) item_ID;
}
AVIF_CHECKRES(avifCheckItemID("infe", itemID, diag));
@@ -3314,7 +3311,7 @@
//
// Since libavif uses repetitionCount (which is 0-based), we subtract the value by 1 to derive the number of
// repetitions.
- assert(track->segmentDuration != 0);
+ AVIF_ASSERT_OR_RETURN(track->segmentDuration != 0);
// We specifically check for trackDuration == 0 here and not when it is actually read in order to accept files which
// inadvertently has a trackDuration of 0 without any edit lists.
if (track->trackDuration == 0) {
@@ -3724,7 +3721,7 @@
// The ExtendedMetaBox may reuse items and properties created above so it must be parsed last.
if (hasExtendedMeta) {
- assert(avifROStreamHasBytesLeft(&s, extendedMetaSize));
+ AVIF_ASSERT_OR_RETURN(avifROStreamHasBytesLeft(&s, extendedMetaSize));
AVIF_CHECKRES(avifParseExtendedMeta(meta, rawOffset + avifROStreamOffset(&s), avifROStreamCurrent(&s), extendedMetaSize, diag));
}
return AVIF_RESULT_OK;
@@ -3792,7 +3789,7 @@
avifBoxHeader header;
AVIF_CHECKERR(avifROStreamReadBoxHeaderPartial(&headerStream, &header), AVIF_RESULT_BMFF_PARSE_FAILED);
parseOffset += headerStream.offset;
- assert((decoder->io->sizeHint == 0) || (parseOffset <= decoder->io->sizeHint));
+ AVIF_ASSERT_OR_RETURN(decoder->io->sizeHint == 0 || parseOffset <= decoder->io->sizeHint);
// Try to get the remainder of the box, if necessary
uint64_t boxOffset = 0;
@@ -4413,7 +4410,7 @@
}
}
}
- assert(alphaItemCount == colorItemCount);
+ AVIF_ASSERT_OR_RETURN(alphaItemCount == colorItemCount);
// Figure out the last used itemID.
avifResult result;
const uint32_t lastID = meta->items.item[meta->items.count - 1]->id;
@@ -4514,7 +4511,7 @@
continue;
}
if (otherItem->dimgIdx < 2) {
- assert(dimgItemIDs[otherItem->dimgIdx] == 0);
+ AVIF_ASSERT_OR_RETURN(dimgItemIDs[otherItem->dimgIdx] == 0);
dimgItemIDs[otherItem->dimgIdx] = otherItem->id;
}
numDimgItemIDs++;
@@ -4563,7 +4560,7 @@
return AVIF_RESULT_OK;
}
- assert(gainMapItemID != 0);
+ AVIF_ASSERT_OR_RETURN(gainMapItemID != 0);
avifDecoderItem * gainMapItemTmp;
AVIF_CHECKRES(avifMetaFindOrCreateItem(data->meta, gainMapItemID, &gainMapItemTmp, data->diag));
if (avifDecoderItemShouldBeSkipped(gainMapItemTmp)) {
@@ -4645,7 +4642,7 @@
AVIF_CHECKERR(item->size != 0, AVIF_RESULT_MISSING_IMAGE_ITEM);
const avifCodecType codecType = avifGetCodecType(item->type);
- assert(codecType != AVIF_CODEC_TYPE_UNKNOWN);
+ AVIF_ASSERT_OR_RETURN(codecType != AVIF_CODEC_TYPE_UNKNOWN);
avifTile * tile =
avifDecoderDataCreateTile(decoder->data, codecType, item->width, item->height, avifDecoderItemOperatingPoint(item));
AVIF_CHECKERR(tile, AVIF_RESULT_OUT_OF_MEMORY);
@@ -4963,7 +4960,7 @@
#endif
if (c == AVIF_ITEM_ALPHA && !mainItems[c]->width && !mainItems[c]->height) {
// NON-STANDARD: Alpha subimage does not have an ispe property; adopt width/height from color item
- assert(!(decoder->strictFlags & AVIF_STRICT_ALPHA_ISPE_REQUIRED));
+ AVIF_ASSERT_OR_RETURN(!(decoder->strictFlags & AVIF_STRICT_ALPHA_ISPE_REQUIRED));
mainItems[c]->width = mainItems[AVIF_ITEM_COLOR]->width;
mainItems[c]->height = mainItems[AVIF_ITEM_COLOR]->height;
}
@@ -4998,7 +4995,7 @@
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
if (mainItems[AVIF_ITEM_GAIN_MAP]) {
- assert(decoder->image->gainMap && decoder->image->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(decoder->image->gainMap && decoder->image->gainMap->image);
decoder->image->gainMap->image->width = mainItems[AVIF_ITEM_GAIN_MAP]->width;
decoder->image->gainMap->image->height = mainItems[AVIF_ITEM_GAIN_MAP]->height;
decoder->gainMapPresent = AVIF_TRUE;
@@ -5188,7 +5185,7 @@
const avifDecodeSample * sample = &tile->input->samples.sample[nextImageIndex];
if (sample->data.size < sample->size) {
- assert(decoder->allowIncremental);
+ AVIF_ASSERT_OR_RETURN(decoder->allowIncremental);
// Data is missing but there is no error yet. Output available pixel rows.
return AVIF_RESULT_OK;
}
@@ -5249,25 +5246,23 @@
avifImage * dstImage = decoder->image;
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) {
- assert(dstImage->gainMap && dstImage->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(dstImage->gainMap && dstImage->gainMap->image);
dstImage = dstImage->gainMap->image;
}
#endif
AVIF_CHECKRES(avifDecoderDataAllocateGridImagePlanes(decoder->data, info, dstImage));
}
- if (!avifDecoderDataCopyTileToImage(decoder->data, info, decoder->image, tile, tileIndex)) {
- return AVIF_RESULT_INVALID_IMAGE_GRID;
- }
+ AVIF_CHECKRES(avifDecoderDataCopyTileToImage(decoder->data, info, decoder->image, tile, tileIndex));
} else {
// Non-grid path. Just steal the planes from the only "tile".
- assert(info->tileCount == 1);
- assert(tileIndex == 0);
+ AVIF_ASSERT_OR_RETURN(info->tileCount == 1);
+ AVIF_ASSERT_OR_RETURN(tileIndex == 0);
avifImage * src = tile->image;
switch (tile->input->itemCategory) {
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
case AVIF_ITEM_GAIN_MAP:
- assert(decoder->image->gainMap && decoder->image->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(decoder->image->gainMap && decoder->image->gainMap->image);
decoder->image->gainMap->image->width = src->width;
decoder->image->gainMap->image->height = src->height;
decoder->image->gainMap->image->depth = src->depth;
@@ -5294,7 +5289,7 @@
avifImageStealPlanes(decoder->image, src, AVIF_PLANES_A);
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
} else if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) {
- assert(decoder->image->gainMap && decoder->image->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(decoder->image->gainMap && decoder->image->gainMap->image);
avifImageStealPlanes(decoder->image->gainMap->image, src, AVIF_PLANES_YUV);
#endif
} else { // AVIF_ITEM_COLOR
@@ -5336,8 +5331,8 @@
}
}
- assert(decoder->data->tiles.count == (decoder->data->tileInfos[AVIF_ITEM_CATEGORY_COUNT - 1].firstTileIndex +
- decoder->data->tileInfos[AVIF_ITEM_CATEGORY_COUNT - 1].tileCount));
+ AVIF_ASSERT_OR_RETURN(decoder->data->tiles.count == (decoder->data->tileInfos[AVIF_ITEM_CATEGORY_COUNT - 1].firstTileIndex +
+ decoder->data->tileInfos[AVIF_ITEM_CATEGORY_COUNT - 1].tileCount));
const uint32_t nextImageIndex = (uint32_t)(decoder->imageIndex + 1);
@@ -5366,22 +5361,22 @@
}
if (!avifDecoderDataFrameFullyDecoded(decoder->data)) {
- assert(decoder->allowIncremental);
+ AVIF_ASSERT_OR_RETURN(decoder->allowIncremental);
// The image is not completely decoded. There should be no error unrelated to missing bytes,
// and at least some missing bytes.
avifResult firstNonOkResult = AVIF_RESULT_OK;
for (int c = 0; c < AVIF_ITEM_CATEGORY_COUNT; ++c) {
- assert((prepareTileResult[c] == AVIF_RESULT_OK) || (prepareTileResult[c] == AVIF_RESULT_WAITING_ON_IO));
+ AVIF_ASSERT_OR_RETURN(prepareTileResult[c] == AVIF_RESULT_OK || prepareTileResult[c] == AVIF_RESULT_WAITING_ON_IO);
if (firstNonOkResult == AVIF_RESULT_OK) {
firstNonOkResult = prepareTileResult[c];
}
}
- assert(firstNonOkResult != AVIF_RESULT_OK);
+ AVIF_ASSERT_OR_RETURN(firstNonOkResult != AVIF_RESULT_OK);
// Return the "not enough bytes" status now instead of moving on to the next frame.
return AVIF_RESULT_WAITING_ON_IO;
}
for (int c = 0; c < AVIF_ITEM_CATEGORY_COUNT; ++c) {
- assert(prepareTileResult[c] == AVIF_RESULT_OK);
+ AVIF_ASSERT_OR_RETURN(prepareTileResult[c] == AVIF_RESULT_OK);
}
// Only advance decoder->imageIndex once the image is completely decoded, so that
@@ -5558,8 +5553,9 @@
const uint32_t scaledGainMapRowCount =
(uint32_t)floorf((float)gainMapRowCount / gainMap->height * decoder->image->height);
// Make sure it matches the formula described in the comment of avifDecoderDecodedRowCount() in avif.h.
- assert((uint32_t)lround((double)scaledGainMapRowCount / decoder->image->height *
- decoder->image->gainMap->image->height) <= gainMapRowCount);
+ AVIF_CHECKERR((uint32_t)lround((double)scaledGainMapRowCount / decoder->image->height *
+ decoder->image->gainMap->image->height) <= gainMapRowCount,
+ 0);
gainMapRowCount = scaledGainMapRowCount;
}
minRowCount = AVIF_MIN(minRowCount, gainMapRowCount);
diff --git a/src/write.c b/src/write.c
index 5881a64..9cbe1f8 100644
--- a/src/write.c
+++ b/src/write.c
@@ -425,7 +425,7 @@
!memcmp(&outputStream->raw->data[property->offset], dedup->buffer.data, newPropertySize)) {
// We've already written this exact property, reuse it
propertyIndex = property->index;
- assert(propertyIndex != 0);
+ AVIF_ASSERT_OR_RETURN(propertyIndex != 0);
break;
}
}
@@ -639,7 +639,7 @@
// of an already stored property.
avifRWStream * dedupStream = outputStream;
if (dedup) {
- assert(ipma);
+ AVIF_ASSERT_OR_RETURN(ipma);
// Use the dedup's temporary stream for box writes.
dedupStream = &dedup->s;
@@ -821,7 +821,7 @@
continue;
}
- assert(!item->hiddenImage);
+ AVIF_ASSERT_OR_RETURN(!item->hiddenImage);
avifBoxMarker infe;
AVIF_CHECKRES(avifRWStreamWriteFullBox(s, "infe", AVIF_BOX_SIZE_TBD, 2, 0, &infe));
AVIF_CHECKRES(avifRWStreamWriteU16(s, item->id)); // unsigned int(16) item_ID;
@@ -1022,36 +1022,23 @@
}
// Same as avifImageCopy() but pads the dstImage with border pixel values to reach dstWidth and dstHeight.
-// Returns NULL if a memory allocation failed.
-static avifImage * avifImageCopyAndPad(const avifImage * srcImage, uint32_t dstWidth, uint32_t dstHeight)
+static avifResult avifImageCopyAndPad(avifImage * const dstImage, const avifImage * srcImage, uint32_t dstWidth, uint32_t dstHeight)
{
- avifImage * dstImage = avifImageCreateEmpty();
- if (!dstImage) {
- return NULL;
- }
- // Copy all fields but do not allocate.
- if (avifImageCopy(dstImage, srcImage, (avifPlanesFlag)0) != AVIF_RESULT_OK) {
- avifImageDestroy(dstImage);
- return NULL;
- }
- assert(dstWidth >= srcImage->width);
- assert(dstHeight >= srcImage->height);
+ AVIF_ASSERT_OR_RETURN(dstImage);
+ AVIF_ASSERT_OR_RETURN(!dstImage->width && !dstImage->height); // dstImage is not set yet.
+ AVIF_ASSERT_OR_RETURN(dstWidth >= srcImage->width);
+ AVIF_ASSERT_OR_RETURN(dstHeight >= srcImage->height);
+
+ // Copy all fields but do not allocate the planes.
+ AVIF_CHECKRES(avifImageCopy(dstImage, srcImage, (avifPlanesFlag)0));
dstImage->width = dstWidth;
dstImage->height = dstHeight;
if (srcImage->yuvPlanes[AVIF_CHAN_Y]) {
- const avifResult allocationResult = avifImageAllocatePlanes(dstImage, AVIF_PLANES_YUV);
- if (allocationResult != AVIF_RESULT_OK) {
- avifImageDestroy(dstImage);
- return NULL;
- }
+ AVIF_CHECKRES(avifImageAllocatePlanes(dstImage, AVIF_PLANES_YUV));
}
if (srcImage->alphaPlane) {
- const avifResult allocationResult = avifImageAllocatePlanes(dstImage, AVIF_PLANES_A);
- if (allocationResult != AVIF_RESULT_OK) {
- avifImageDestroy(dstImage);
- return NULL;
- }
+ AVIF_CHECKRES(avifImageAllocatePlanes(dstImage, AVIF_PLANES_A));
}
const avifBool usesU16 = avifImageUsesU16(srcImage);
for (int plane = AVIF_CHAN_Y; plane <= AVIF_CHAN_A; ++plane) {
@@ -1091,7 +1078,7 @@
dstRow += dstRowBytes;
}
}
- return dstImage;
+ return AVIF_RESULT_OK;
}
static int avifQualityToQuantizer(int quality, int minQuantizer, int maxQuantizer)
@@ -1242,9 +1229,9 @@
const avifImage * bottomRightCell = cellImages[cellCount - 1];
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
if (validateGainMap) {
- assert(firstCell->gainMap && firstCell->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(firstCell->gainMap && firstCell->gainMap->image);
firstCell = firstCell->gainMap->image;
- assert(bottomRightCell->gainMap && bottomRightCell->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(bottomRightCell->gainMap && bottomRightCell->gainMap->image);
bottomRightCell = bottomRightCell->gainMap->image;
}
#endif
@@ -1256,7 +1243,7 @@
const avifImage * cellImage = cellImages[cellIndex];
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
if (validateGainMap) {
- assert(cellImage->gainMap && cellImage->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(cellImage->gainMap && cellImage->gainMap->image);
cellImage = cellImage->gainMap->image;
}
#endif
@@ -1530,12 +1517,12 @@
uint16_t alphaItemID;
AVIF_CHECKRES(avifEncoderAddImageItems(encoder, gridCols, gridRows, gridWidth, gridHeight, AVIF_ITEM_ALPHA, &alphaItemID));
avifEncoderItem * alphaItem = avifEncoderDataFindItemByID(encoder->data, alphaItemID);
- assert(alphaItem);
+ AVIF_ASSERT_OR_RETURN(alphaItem);
alphaItem->irefType = "auxl";
alphaItem->irefToID = colorItemID;
if (encoder->data->imageMetadata->alphaPremultiplied) {
avifEncoderItem * colorItem = avifEncoderDataFindItemByID(encoder->data, colorItemID);
- assert(colorItem);
+ AVIF_ASSERT_OR_RETURN(colorItem);
colorItem->irefType = "prem";
colorItem->irefToID = alphaItemID;
}
@@ -1573,17 +1560,17 @@
AVIF_CHECKRES(
avifEncoderAddImageItems(encoder, gridCols, gridRows, gainMapGridWidth, gainMapGridHeight, AVIF_ITEM_GAIN_MAP, &gainMapItemID));
avifEncoderItem * gainMapItem = avifEncoderDataFindItemByID(encoder->data, gainMapItemID);
- assert(gainMapItem);
+ AVIF_ASSERT_OR_RETURN(gainMapItem);
gainMapItem->hiddenImage = AVIF_TRUE;
// Set the color item and gain map item's dimgFromID value to point to the tone mapped item.
// The color item shall be first, and the gain map second. avifEncoderFinish() writes the
// dimg item references in item id order, so as long as colorItemID < gainMapItemID, the order
// will be correct.
- assert(colorItemID < gainMapItemID);
+ AVIF_ASSERT_OR_RETURN(colorItemID < gainMapItemID);
avifEncoderItem * colorItem = avifEncoderDataFindItemByID(encoder->data, colorItemID);
- assert(colorItem);
- assert(colorItem->dimgFromID == 0); // Our internal API only allows one dimg value per item.
+ AVIF_ASSERT_OR_RETURN(colorItem);
+ AVIF_ASSERT_OR_RETURN(colorItem->dimgFromID == 0); // Our internal API only allows one dimg value per item.
colorItem->dimgFromID = toneMappedItemID;
gainMapItem->dimgFromID = toneMappedItemID;
}
@@ -1643,11 +1630,9 @@
// }
// Check whether it is safe to cast width and height to uint16_t. The maximum width and
// height of an AV1 frame are 65536, which just exceeds uint16_t.
- assert(encoder->data->items.count > 0);
+ AVIF_ASSERT_OR_RETURN(encoder->data->items.count > 0);
const avifImage * imageMetadata = encoder->data->imageMetadata;
- if ((imageMetadata->width > 65535) || (imageMetadata->height > 65535)) {
- return AVIF_RESULT_INVALID_ARGUMENT;
- }
+ AVIF_CHECKERR(imageMetadata->width <= 65535 && imageMetadata->height <= 65535, AVIF_RESULT_INVALID_ARGUMENT);
}
// -----------------------------------------------------------------------
@@ -1660,17 +1645,20 @@
const avifImage * firstCellImage = firstCell;
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
if (item->itemCategory == AVIF_ITEM_GAIN_MAP) {
- assert(cellImage->gainMap && cellImage->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(cellImage->gainMap && cellImage->gainMap->image);
cellImage = cellImage->gainMap->image;
- assert(firstCell->gainMap && firstCell->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(firstCell->gainMap && firstCell->gainMap->image);
firstCellImage = firstCell->gainMap->image;
}
#endif
avifImage * paddedCellImage = NULL;
if ((cellImage->width != firstCellImage->width) || (cellImage->height != firstCellImage->height)) {
- paddedCellImage = avifImageCopyAndPad(cellImage, firstCellImage->width, firstCellImage->height);
- if (!paddedCellImage) {
- return AVIF_RESULT_OUT_OF_MEMORY;
+ paddedCellImage = avifImageCreateEmpty();
+ AVIF_CHECKERR(paddedCellImage, AVIF_RESULT_OUT_OF_MEMORY);
+ const avifResult result = avifImageCopyAndPad(paddedCellImage, cellImage, firstCellImage->width, firstCellImage->height);
+ if (result != AVIF_RESULT_OK) {
+ avifImageDestroy(paddedCellImage);
+ return result;
}
cellImage = paddedCellImage;
}
@@ -1804,7 +1792,7 @@
if ((encoder->extraLayerCount > 0) && (item->encodeOutput->samples.count > 0)) {
// Interleave - Pick out AV1 items and interleave them later.
// We always interleave all AV1 items for layered images.
- assert(item->encodeOutput->samples.count == item->mdatFixups.count);
+ AVIF_ASSERT_OR_RETURN(item->encodeOutput->samples.count == item->mdatFixups.count);
avifEncoderItemReference * ref = (item->itemCategory == AVIF_ITEM_ALPHA) ? avifArrayPush(layeredAlphaItems)
: avifArrayPush(layeredColorItems);
@@ -1905,7 +1893,7 @@
++layerIndex;
} while (hasMoreSample);
- assert(layerIndex <= AVIF_MAX_AV1_LAYER_COUNT);
+ AVIF_ASSERT_OR_RETURN(layerIndex <= AVIF_MAX_AV1_LAYER_COUNT);
}
avifRWStreamFinishBox(s, mdat);
return AVIF_RESULT_OK;
@@ -1964,7 +1952,7 @@
((imageMetadata->transformFlags & AVIF_TRANSFORM_IROT) ? 1 : 0) +
((imageMetadata->transformFlags & AVIF_TRANSFORM_IMIR) ? 1 : 0);
const uint8_t ipmaCount = numNonEssentialProperties + numEssentialProperties;
- assert(ipmaCount >= 1);
+ AVIF_ASSERT_OR_RETURN(ipmaCount >= 1);
// Only add properties to the primary item.
AVIF_CHECKRES(avifRWStreamWriteU32(stream, 1)); // unsigned int(32) entry_count;
@@ -2074,15 +2062,15 @@
avifEncoderItem * item = &encoder->data->items.item[itemIndex];
if (item->id == encoder->data->primaryItemID) {
colorItem = item;
- assert(colorItem->encodeOutput->samples.count == 1);
+ AVIF_ASSERT_OR_RETURN(colorItem->encodeOutput->samples.count == 1);
} else if (item->itemCategory == AVIF_ITEM_ALPHA && item->irefToID == encoder->data->primaryItemID) {
- assert(!alphaItem);
+ AVIF_ASSERT_OR_RETURN(!alphaItem);
alphaItem = item;
- assert(alphaItem->encodeOutput->samples.count == 1);
+ AVIF_ASSERT_OR_RETURN(alphaItem->encodeOutput->samples.count == 1);
}
}
- assert(colorItem);
+ AVIF_ASSERT_OR_RETURN(colorItem);
const avifRWData * colorData = &colorItem->encodeOutput->samples.sample[0].data;
const avifRWData * alphaData = alphaItem ? &alphaItem->encodeOutput->samples.sample[0].data : NULL;
@@ -2146,7 +2134,7 @@
// unsigned int(32) infe_type;
// unsigned int(32) codec_config_type;
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, 4)); // varint main_item_codec_config_size;
- assert(colorData->size >= 1);
+ AVIF_ASSERT_OR_RETURN(colorData->size >= 1);
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, (uint32_t)colorData->size - 1)); // varint main_item_data_size_minus_one;
AVIF_CHECKRES(avifRWStreamWriteBits(s, alphaItem ? 1 : 0, 1)); // unsigned int(1) has_alpha;
@@ -2253,7 +2241,7 @@
if (isToneMappedImage) {
itemMetadata = altImageMetadata;
} else if (item->itemCategory == AVIF_ITEM_GAIN_MAP) {
- assert(itemMetadata->gainMap && itemMetadata->gainMap->image);
+ AVIF_ASSERT_OR_RETURN(itemMetadata->gainMap && itemMetadata->gainMap->image);
itemMetadata = itemMetadata->gainMap->image;
}
#else
@@ -2761,7 +2749,7 @@
durationInTimescales = AVIF_INDEFINITE_DURATION64;
} else {
uint64_t loopCount = encoder->repetitionCount + 1;
- assert(framesDurationInTimescales != 0);
+ AVIF_ASSERT_OR_RETURN(framesDurationInTimescales != 0);
if (loopCount > UINT64_MAX / framesDurationInTimescales) {
// The multiplication will overflow uint64_t.
return AVIF_RESULT_INVALID_ARGUMENT;