#include "avif/internal.h"
#include <assert.h>
#include <ctype.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#define AUXTYPE_SIZE …
#define CONTENTTYPE_SIZE …
static const size_t VISUALSAMPLEENTRY_SIZE = …;
#define MAX_IPMA_VERSION_AND_FLAGS_SEEN …
static avifCodecType avifGetCodecType(const uint8_t * fourcc)
{ … }
static const char * avifGetConfigurationPropertyName(avifCodecType codecType)
{ … }
avifBrand;
AVIF_ARRAY_DECLARE(avifBrandArray, avifBrand, … } ;
avifFileType;
avifImageSpatialExtents;
avifAuxiliaryType;
avifContentType;
avifColourInformationBox;
#define MAX_PIXI_PLANE_DEPTHS …
avifPixelInformationProperty;
avifOperatingPointSelectorProperty;
avifLayerSelectorProperty;
avifAV1LayeredImageIndexingProperty;
struct avifMeta;
avifProperty;
AVIF_ARRAY_DECLARE(avifPropertyArray, avifProperty, … } ;
static const avifProperty * avifPropertyArrayFind(const avifPropertyArray * properties, const char * type)
{ … }
AVIF_ARRAY_DECLARE(avifExtentArray, avifExtent, … } ;
avifDecoderItem;
AVIF_ARRAY_DECLARE(avifDecoderItemArray, avifDecoderItem … } ;
avifImageGrid;
avifSampleTableChunk;
AVIF_ARRAY_DECLARE(avifSampleTableChunkArray, avifSampleTableChunk, … } ;
avifSampleTableSampleToChunk;
AVIF_ARRAY_DECLARE(avifSampleTableSampleToChunkArray, avifSampleTableSampleToChunk, … } ;
avifSampleTableSampleSize;
AVIF_ARRAY_DECLARE(avifSampleTableSampleSizeArray, avifSampleTableSampleSize, … } ;
avifSampleTableTimeToSample;
AVIF_ARRAY_DECLARE(avifSampleTableTimeToSampleArray, avifSampleTableTimeToSample, … } ;
avifSyncSample;
AVIF_ARRAY_DECLARE(avifSyncSampleArray, avifSyncSample, … } ;
avifSampleDescription;
AVIF_ARRAY_DECLARE(avifSampleDescriptionArray, avifSampleDescription, … } ;
avifSampleTable;
static void avifSampleTableDestroy(avifSampleTable * sampleTable);
static avifSampleTable * avifSampleTableCreate(void)
{ … }
static void avifSampleTableDestroy(avifSampleTable * sampleTable)
{ … }
static uint32_t avifSampleTableGetImageDelta(const avifSampleTable * sampleTable, uint32_t imageIndex)
{ … }
static avifCodecType avifSampleTableGetCodecType(const avifSampleTable * sampleTable)
{ … }
static uint32_t avifCodecConfigurationBoxGetDepth(const avifCodecConfigurationBox * av1C)
{ … }
static avifPixelFormat avifCodecConfigurationBoxGetFormat(const avifCodecConfigurationBox * av1C)
{ … }
static const avifPropertyArray * avifSampleTableGetProperties(const avifSampleTable * sampleTable, avifCodecType codecType)
{ … }
avifTrack;
AVIF_ARRAY_DECLARE(avifTrackArray, avifTrack, … } ;
avifCodecDecodeInput * avifCodecDecodeInputCreate(void)
{ … }
void avifCodecDecodeInputDestroy(avifCodecDecodeInput * decodeInput)
{ … }
static uint32_t avifGetSampleCountOfChunk(const avifSampleTableSampleToChunkArray * sampleToChunks, uint32_t chunkIndex)
{ … }
static avifResult avifCodecDecodeInputFillFromSampleTable(avifCodecDecodeInput * decodeInput,
avifSampleTable * sampleTable,
const uint32_t imageCountLimit,
const uint64_t sizeHint,
avifDiagnostics * diag)
{ … }
static avifResult avifCodecDecodeInputFillFromDecoderItem(avifCodecDecodeInput * decodeInput,
avifDecoderItem * item,
avifBool allowProgressive,
const uint32_t imageCountLimit,
const uint64_t sizeHint,
avifDiagnostics * diag)
{ … }
#define BEGIN_STREAM(VARNAME, PTR, SIZE, DIAG, CONTEXT) …
static avifBool uniqueBoxSeen(uint32_t * uniqueBoxFlags, uint32_t whichFlag, const char * parentBoxType, const char * boxType, avifDiagnostics * diagnostics)
{ … }
avifTile;
AVIF_ARRAY_DECLARE(avifTileArray, avifTile, … } ;
avifMeta;
static void avifMetaDestroy(avifMeta * meta);
static avifMeta * avifMetaCreate(void)
{ … }
static void avifMetaDestroy(avifMeta * meta)
{ … }
static avifResult avifCheckItemID(const char * boxFourcc, uint32_t itemID, avifDiagnostics * diag)
{ … }
static avifResult avifMetaFindOrCreateItem(avifMeta * meta, uint32_t itemID, avifDecoderItem ** item)
{ … }
avifTileInfo;
avifDecoderData;
static void avifDecoderDataDestroy(avifDecoderData * data);
static avifDecoderData * avifDecoderDataCreate(void)
{ … }
static void avifDecoderDataResetCodec(avifDecoderData * data)
{ … }
static avifTile * avifDecoderDataCreateTile(avifDecoderData * data, avifCodecType codecType, uint32_t width, uint32_t height, uint8_t operatingPoint)
{ … }
static avifTrack * avifDecoderDataCreateTrack(avifDecoderData * data)
{ … }
static void avifDecoderDataClearTiles(avifDecoderData * data)
{ … }
static void avifDecoderDataDestroy(avifDecoderData * data)
{ … }
static avifResult avifDecoderItemMaxExtent(const avifDecoderItem * item, const avifDecodeSample * sample, avifExtent * outExtent)
{ … }
static uint8_t avifDecoderItemOperatingPoint(const avifDecoderItem * item)
{ … }
static avifResult avifDecoderItemValidateProperties(const avifDecoderItem * item,
const char * configPropName,
avifDiagnostics * diag,
const avifStrictFlags strictFlags)
{ … }
static avifResult avifDecoderItemRead(avifDecoderItem * item,
avifIO * io,
avifROData * outData,
size_t offset,
size_t partialByteCount,
avifDiagnostics * diag)
{ … }
static avifCodecType avifDecoderItemGetGridCodecType(const avifDecoderItem * gridItem)
{ … }
static avifResult avifFillDimgIdxToItemIdxArray(uint32_t * dimgIdxToItemIdx, uint32_t numExpectedTiles, const avifDecoderItem * gridItem)
{ … }
static avifResult avifDecoderGenerateImageGridTiles(avifDecoder * decoder,
avifDecoderItem * gridItem,
avifItemCategory itemCategory,
const uint32_t * dimgIdxToItemIdx,
uint32_t numTiles)
{ … }
static avifResult avifDecoderDataAllocateImagePlanes(avifDecoderData * data, const avifTileInfo * info, avifImage * dstImage)
{ … }
static avifResult avifDecoderDataCopyTileToImage(avifDecoderData * data,
const avifTileInfo * info,
avifImage * dstImage,
const avifTile * tile,
unsigned int tileIndex)
{ … }
static avifResult avifDecoderFindMetadata(avifDecoder * decoder, avifMeta * meta, avifImage * image, uint32_t colorId)
{ … }
static avifBool isAlphaURN(const char * urn)
{ … }
static avifBool avifParseHandlerBox(const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseItemLocationBox(avifMeta * meta, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseImageGridBox(avifImageGrid * grid,
const uint8_t * raw,
size_t rawLen,
uint32_t imageSizeLimit,
uint32_t imageDimensionLimit,
avifDiagnostics * diag)
{ … }
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
static avifBool avifParseGainMapMetadata(avifGainMapMetadata * metadata, avifROStream * s)
{ … }
static avifResult avifParseToneMappedImageBox(avifGainMapMetadata * metadata, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
#endif
#if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM)
static avifResult avifParseSampleTransformTokens(avifROStream * s, avifSampleTransformExpression * expression)
{
uint8_t tokenCount;
AVIF_CHECK(avifROStreamRead(s, &tokenCount, 1));
AVIF_CHECKERR(tokenCount != 0, AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifArrayCreate(expression, sizeof(expression->tokens[0]), tokenCount), AVIF_RESULT_OUT_OF_MEMORY);
for (uint32_t t = 0; t < tokenCount; ++t) {
avifSampleTransformToken * token = (avifSampleTransformToken *)avifArrayPush(expression);
AVIF_CHECKERR(token != NULL, AVIF_RESULT_OUT_OF_MEMORY);
AVIF_CHECK(avifROStreamRead(s, &token->type, 1));
if (token->type == AVIF_SAMPLE_TRANSFORM_CONSTANT) {
uint32_t constant;
AVIF_CHECK(avifROStreamReadU32(s, &constant));
token->constant = *(int32_t *)&constant;
} else if (token->type == AVIF_SAMPLE_TRANSFORM_INPUT_IMAGE_ITEM_INDEX) {
AVIF_CHECK(avifROStreamRead(s, &token->inputImageItemIndex, 1));
}
}
AVIF_CHECKERR(avifROStreamRemainingBytes(s) == 0, AVIF_RESULT_BMFF_PARSE_FAILED);
return AVIF_RESULT_OK;
}
static avifResult avifParseSampleTransformImageBox(const uint8_t * raw,
size_t rawLen,
uint32_t numInputImageItems,
avifSampleTransformExpression * expression,
avifDiagnostics * diag)
{
BEGIN_STREAM(s, raw, rawLen, diag, "Box[sato]");
uint8_t version, bitDepth;
AVIF_CHECK(avifROStreamReadBits8(&s, &version, 6));
AVIF_CHECK(avifROStreamReadBits8(&s, &bitDepth, 2));
AVIF_CHECKERR(version == 0, AVIF_RESULT_NOT_IMPLEMENTED);
AVIF_CHECKERR(bitDepth == AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_32, AVIF_RESULT_NOT_IMPLEMENTED);
const avifResult result = avifParseSampleTransformTokens(&s, expression);
if (result != AVIF_RESULT_OK) {
avifArrayDestroy(expression);
return result;
}
if (!avifSampleTransformExpressionIsValid(expression, numInputImageItems)) {
avifArrayDestroy(expression);
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
return AVIF_RESULT_OK;
}
static avifResult avifDecoderSampleTransformItemValidateProperties(const avifDecoderItem * item, avifDiagnostics * diag)
{
const avifProperty * pixiProp = avifPropertyArrayFind(&item->properties, "pixi");
if (!pixiProp) {
avifDiagnosticsPrintf(diag, "Item ID %u of type '%.4s' is missing mandatory pixi property", item->id, (const char *)item->type);
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
for (uint8_t i = 0; i < pixiProp->u.pixi.planeCount; ++i) {
if (pixiProp->u.pixi.planeDepths[i] != pixiProp->u.pixi.planeDepths[0]) {
avifDiagnosticsPrintf(diag,
"Item ID %u of type '%.4s' has different depths specified by pixi property [%u, %u], this is not supported",
item->id,
(const char *)item->type,
pixiProp->u.pixi.planeDepths[0],
pixiProp->u.pixi.planeDepths[i]);
return AVIF_RESULT_NOT_IMPLEMENTED;
}
}
const avifProperty * ispeProp = avifPropertyArrayFind(&item->properties, "ispe");
if (!ispeProp) {
avifDiagnosticsPrintf(diag, "Item ID %u of type '%.4s' is missing mandatory ispe property", item->id, (const char *)item->type);
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
for (uint32_t i = 0; i < item->meta->items.count; ++i) {
avifDecoderItem * inputImageItem = item->meta->items.item[i];
if (inputImageItem->dimgForID != item->id) {
continue;
}
const avifProperty * inputImageItemIspeProp = avifPropertyArrayFind(&inputImageItem->properties, "ispe");
AVIF_ASSERT_OR_RETURN(inputImageItemIspeProp != NULL);
if (inputImageItemIspeProp->u.ispe.width != ispeProp->u.ispe.width ||
inputImageItemIspeProp->u.ispe.height != ispeProp->u.ispe.height) {
avifDiagnosticsPrintf(diag,
"The fields of the ispe property of item ID %u of type '%.4s' differs from item ID %u",
inputImageItem->id,
(const char *)inputImageItem->type,
item->id);
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
}
AVIF_CHECKERR(avifPropertyArrayFind(&item->properties, "clap") == NULL, AVIF_RESULT_NOT_IMPLEMENTED);
return AVIF_RESULT_OK;
}
#endif
static avifResult avifDecoderItemReadAndParse(const avifDecoder * decoder,
avifDecoderItem * item,
avifBool isItemInInput,
avifImageGrid * grid,
avifCodecType * codecType)
{ … }
static avifBool avifParseImageSpatialExtentsProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseAuxiliaryTypeProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseColourInformationBox(avifProperty * prop, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseContentLightLevelInformationBox(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseCodecConfiguration(avifROStream * s, avifCodecConfigurationBox * config, const char * configPropName, avifDiagnostics * diag)
{ … }
static avifBool avifParseCodecConfigurationBoxProperty(avifProperty * prop,
const uint8_t * raw,
size_t rawLen,
const char * configPropName,
avifDiagnostics * diag)
{ … }
static avifBool avifParsePixelAspectRatioBoxProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseCleanApertureBoxProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseImageRotationProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseImageMirrorProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParsePixelInformationProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseOperatingPointSelectorProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseLayerSelectorProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseAV1LayeredImageIndexingProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseItemPropertyContainerBox(avifPropertyArray * properties,
uint64_t rawOffset,
const uint8_t * raw,
size_t rawLen,
avifDiagnostics * diag)
{ … }
static avifResult avifParseItemPropertyAssociation(avifMeta * meta, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag, uint32_t * outVersionAndFlags)
{ … }
static avifBool avifParsePrimaryItemBox(avifMeta * meta, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseItemDataBox(avifMeta * meta, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseItemPropertiesBox(avifMeta * meta, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseItemInfoEntry(avifMeta * meta, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseItemInfoBox(avifMeta * meta, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseItemReferenceBox(avifMeta * meta, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseMetaBox(avifMeta * meta, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseTrackHeaderBox(avifTrack * track,
const uint8_t * raw,
size_t rawLen,
uint32_t imageSizeLimit,
uint32_t imageDimensionLimit,
avifDiagnostics * diag)
{ … }
static avifBool avifParseMediaHeaderBox(avifTrack * track, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseChunkOffsetBox(avifSampleTable * sampleTable, avifBool largeOffsets, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseSampleToChunkBox(avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseSampleSizeBox(avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseSyncSampleBox(avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseTimeToSampleBox(avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseSampleDescriptionBox(avifSampleTable * sampleTable,
uint64_t rawOffset,
const uint8_t * raw,
size_t rawLen,
avifDiagnostics * diag)
{ … }
static avifResult avifParseSampleTableBox(avifTrack * track, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseMediaInformationBox(avifTrack * track, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseMediaBox(avifTrack * track, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifTrackReferenceBox(avifTrack * track, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseEditListBox(avifTrack * track, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifParseEditBox(avifTrack * track, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifResult avifParseTrackBox(avifDecoderData * data,
uint64_t rawOffset,
const uint8_t * raw,
size_t rawLen,
uint32_t imageSizeLimit,
uint32_t imageDimensionLimit)
{ … }
static avifResult avifParseMovieBox(avifDecoderData * data,
uint64_t rawOffset,
const uint8_t * raw,
size_t rawLen,
uint32_t imageSizeLimit,
uint32_t imageDimensionLimit)
{ … }
#if defined(AVIF_ENABLE_EXPERIMENTAL_MINI)
static avifProperty * avifMetaCreateProperty(avifMeta * meta, const char * propertyType)
{
avifProperty * metaProperty = avifArrayPush(&meta->properties);
AVIF_CHECK(metaProperty);
memcpy(metaProperty->type, propertyType, 4);
return metaProperty;
}
static avifProperty * avifDecoderItemAddProperty(avifDecoderItem * item, const avifProperty * metaProperty)
{
avifProperty * itemProperty = avifArrayPush(&item->properties);
AVIF_CHECK(itemProperty);
*itemProperty = *metaProperty;
return itemProperty;
}
static avifResult avifParseMinimizedImageBox(avifMeta * meta,
uint64_t rawOffset,
const uint8_t * raw,
size_t rawLen,
avifBool isAvifAccordingToMinorVersion,
avifDiagnostics * diag)
{
BEGIN_STREAM(s, raw, rawLen, diag, "Box[mini]");
meta->fromMiniBox = AVIF_TRUE;
uint32_t version;
AVIF_CHECKERR(avifROStreamReadBits(&s, &version, 2), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(version == 0, AVIF_RESULT_BMFF_PARSE_FAILED);
uint32_t hasExplicitCodecTypes, floatFlag, fullRange, hasAlpha, hasExplicitCicp, hasHdr, hasIcc, hasExif, hasXmp;
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasExplicitCodecTypes, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &floatFlag, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &fullRange, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasAlpha, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasExplicitCicp, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasHdr, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasIcc, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasExif, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasXmp, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
uint32_t chromaSubsampling, orientation;
AVIF_CHECKERR(avifROStreamReadBits(&s, &chromaSubsampling, 2), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &orientation, 3), AVIF_RESULT_BMFF_PARSE_FAILED);
++orientation;
uint32_t smallDimensionsFlag, width, height;
AVIF_CHECKERR(avifROStreamReadBits(&s, &smallDimensionsFlag, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &width, smallDimensionsFlag ? 7 : 15),
AVIF_RESULT_BMFF_PARSE_FAILED);
++width;
AVIF_CHECKERR(avifROStreamReadBits(&s, &height, smallDimensionsFlag ? 7 : 15),
AVIF_RESULT_BMFF_PARSE_FAILED);
++height;
uint32_t chromaIsHorizontallyCentered = 0, chromaIsVerticallyCentered = 0;
if (chromaSubsampling == 1 || chromaSubsampling == 2) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &chromaIsHorizontallyCentered, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
}
if (chromaSubsampling == 1) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &chromaIsVerticallyCentered, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
}
uint32_t bitDepth;
if (floatFlag) {
return AVIF_RESULT_BMFF_PARSE_FAILED;
} else {
uint32_t highBitDepthFlag;
AVIF_CHECKERR(avifROStreamReadBits(&s, &highBitDepthFlag, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
if (highBitDepthFlag) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &bitDepth, 3), AVIF_RESULT_BMFF_PARSE_FAILED);
bitDepth += 9;
} else {
bitDepth = 8;
}
}
uint32_t alphaIsPremultiplied = 0;
if (hasAlpha) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &alphaIsPremultiplied, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
}
uint8_t colorPrimaries;
uint8_t transferCharacteristics;
uint8_t matrixCoefficients;
if (hasExplicitCicp) {
AVIF_CHECKERR(avifROStreamReadBits8(&s, &colorPrimaries, 8), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits8(&s, &transferCharacteristics, 8), AVIF_RESULT_BMFF_PARSE_FAILED);
if (chromaSubsampling != 0) {
AVIF_CHECKERR(avifROStreamReadBits8(&s, &matrixCoefficients, 8), AVIF_RESULT_BMFF_PARSE_FAILED);
} else {
matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED;
}
} else {
colorPrimaries = hasIcc ? AVIF_COLOR_PRIMARIES_UNSPECIFIED
: AVIF_COLOR_PRIMARIES_BT709;
transferCharacteristics = hasIcc ? AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED
: AVIF_TRANSFER_CHARACTERISTICS_SRGB;
matrixCoefficients = chromaSubsampling == 0 ? AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED
: AVIF_MATRIX_COEFFICIENTS_BT601;
}
uint8_t infeType[4];
uint8_t codecConfigType[4];
if (hasExplicitCodecTypes) {
for (int i = 0; i < 4; ++i) {
AVIF_CHECKERR(avifROStreamReadBits8(&s, &infeType[i], 8), AVIF_RESULT_BMFF_PARSE_FAILED);
}
for (int i = 0; i < 4; ++i) {
AVIF_CHECKERR(avifROStreamReadBits8(&s, &codecConfigType[i], 8), AVIF_RESULT_BMFF_PARSE_FAILED);
}
#if defined(AVIF_CODEC_AVM)
if (!memcmp(infeType, "av02", 4) && !memcmp(codecConfigType, "av2C", 4)) {
return AVIF_RESULT_NOT_IMPLEMENTED;
}
#endif
AVIF_CHECKERR(!memcmp(infeType, "av01", 4) && !memcmp(codecConfigType, "av1C", 4), AVIF_RESULT_BMFF_PARSE_FAILED);
} else {
AVIF_CHECKERR(isAvifAccordingToMinorVersion, AVIF_RESULT_BMFF_PARSE_FAILED);
memcpy(infeType, "av01", 4);
memcpy(codecConfigType, "av1C", 4);
}
uint32_t hasGainmap = AVIF_FALSE;
if (hasHdr) {
return AVIF_RESULT_NOT_IMPLEMENTED;
}
uint32_t fewMetadataBytesFlag = 0, fewCodecConfigBytesFlag = 0, fewItemDataBytesFlag = 0;
if (hasIcc || hasExif || hasXmp || (hasHdr && hasGainmap)) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &fewMetadataBytesFlag, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
}
AVIF_CHECKERR(avifROStreamReadBits(&s, &fewCodecConfigBytesFlag, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &fewItemDataBytesFlag, 1), AVIF_RESULT_BMFF_PARSE_FAILED);
uint32_t iccDataSize = 0;
if (hasIcc) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &iccDataSize, fewMetadataBytesFlag ? 10 : 20),
AVIF_RESULT_BMFF_PARSE_FAILED);
++iccDataSize;
}
uint32_t mainItemCodecConfigSize, mainItemDataSize;
AVIF_CHECKERR(avifROStreamReadBits(&s, &mainItemCodecConfigSize, fewCodecConfigBytesFlag ? 3 : 12),
AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamReadBits(&s, &mainItemDataSize, fewItemDataBytesFlag ? 15 : 28),
AVIF_RESULT_BMFF_PARSE_FAILED);
++mainItemDataSize;
uint32_t alphaItemCodecConfigSize = 0, alphaItemDataSize = 0;
if (hasAlpha) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &alphaItemDataSize, fewItemDataBytesFlag ? 15 : 28),
AVIF_RESULT_BMFF_PARSE_FAILED);
}
if (hasAlpha && alphaItemDataSize != 0) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &alphaItemCodecConfigSize, fewCodecConfigBytesFlag ? 3 : 12),
AVIF_RESULT_BMFF_PARSE_FAILED);
}
uint32_t exifDataSize = 0;
if (hasExif) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &exifDataSize, fewMetadataBytesFlag ? 10 : 20),
AVIF_RESULT_BMFF_PARSE_FAILED);
++exifDataSize;
}
uint32_t xmpDataSize = 0;
if (hasXmp) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &xmpDataSize, fewMetadataBytesFlag ? 10 : 20),
AVIF_RESULT_BMFF_PARSE_FAILED);
++xmpDataSize;
}
if (s.numUsedBitsInPartialByte) {
uint32_t padding;
AVIF_CHECKERR(avifROStreamReadBits(&s, &padding, 8 - s.numUsedBitsInPartialByte), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(!padding, AVIF_RESULT_BMFF_PARSE_FAILED);
}
avifCodecConfigurationBox alphaItemCodecConfig = { 0 };
if (hasAlpha && alphaItemDataSize != 0 && alphaItemCodecConfigSize != 0) {
AVIF_CHECKERR(alphaItemCodecConfigSize == 4, AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifParseCodecConfiguration(&s, &alphaItemCodecConfig, (const char *)codecConfigType, diag),
AVIF_RESULT_BMFF_PARSE_FAILED);
}
avifCodecConfigurationBox mainItemCodecConfig;
AVIF_CHECKERR(mainItemCodecConfigSize == 4, AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifParseCodecConfiguration(&s, &mainItemCodecConfig, (const char *)codecConfigType, diag),
AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifROStreamRemainingBytes(&s) == (uint64_t)iccDataSize + alphaItemDataSize + mainItemDataSize + exifDataSize + xmpDataSize,
AVIF_RESULT_BMFF_PARSE_FAILED);
meta->primaryItemID = 1;
avifDecoderItem * colorItem;
AVIF_CHECKRES(avifMetaFindOrCreateItem(meta, meta->primaryItemID, &colorItem));
memcpy(colorItem->type, infeType, 4);
colorItem->width = width;
colorItem->height = height;
colorItem->miniBoxPixelFormat = chromaSubsampling == 0 ? AVIF_PIXEL_FORMAT_YUV400
: chromaSubsampling == 1 ? AVIF_PIXEL_FORMAT_YUV420
: chromaSubsampling == 2 ? AVIF_PIXEL_FORMAT_YUV422
: AVIF_PIXEL_FORMAT_YUV444;
if (colorItem->miniBoxPixelFormat == AVIF_PIXEL_FORMAT_YUV422) {
AVIF_CHECKERR(!chromaIsHorizontallyCentered, AVIF_RESULT_BMFF_PARSE_FAILED);
colorItem->miniBoxChromaSamplePosition = AVIF_CHROMA_SAMPLE_POSITION_UNKNOWN;
} else if (colorItem->miniBoxPixelFormat == AVIF_PIXEL_FORMAT_YUV420) {
if (chromaIsHorizontallyCentered) {
colorItem->miniBoxChromaSamplePosition = AVIF_CHROMA_SAMPLE_POSITION_UNKNOWN;
} else {
colorItem->miniBoxChromaSamplePosition = chromaIsVerticallyCentered ? AVIF_CHROMA_SAMPLE_POSITION_VERTICAL
: AVIF_CHROMA_SAMPLE_POSITION_COLOCATED;
}
} else {
colorItem->miniBoxChromaSamplePosition = AVIF_CHROMA_SAMPLE_POSITION_UNKNOWN;
}
avifDecoderItem * alphaItem = NULL;
if (hasAlpha) {
AVIF_CHECKRES(avifMetaFindOrCreateItem(meta, 2, &alphaItem));
memcpy(alphaItem->type, infeType, 4);
alphaItem->width = width;
alphaItem->height = height;
alphaItem->miniBoxPixelFormat = AVIF_PIXEL_FORMAT_YUV400;
alphaItem->miniBoxChromaSamplePosition = AVIF_CHROMA_SAMPLE_POSITION_UNKNOWN;
}
avifProperty * colorCodecConfigProp = avifMetaCreateProperty(meta, (const char *)codecConfigType);
AVIF_CHECKERR(colorCodecConfigProp, AVIF_RESULT_OUT_OF_MEMORY);
colorCodecConfigProp->u.av1C = mainItemCodecConfig;
AVIF_CHECKERR(avifDecoderItemAddProperty(colorItem, colorCodecConfigProp), AVIF_RESULT_OUT_OF_MEMORY);
avifProperty * ispeProp = avifMetaCreateProperty(meta, "ispe");
AVIF_CHECKERR(ispeProp, AVIF_RESULT_OUT_OF_MEMORY);
ispeProp->u.ispe.width = width;
ispeProp->u.ispe.height = height;
AVIF_CHECKERR(avifDecoderItemAddProperty(colorItem, ispeProp), AVIF_RESULT_OUT_OF_MEMORY);
avifProperty * pixiProp = avifMetaCreateProperty(meta, "pixi");
AVIF_CHECKERR(pixiProp, AVIF_RESULT_OUT_OF_MEMORY);
pixiProp->u.pixi.planeCount = chromaSubsampling == 0 ? 1 : 3;
for (uint8_t plane = 0; plane < pixiProp->u.pixi.planeCount; ++plane) {
pixiProp->u.pixi.planeDepths[plane] = (uint8_t)bitDepth;
}
AVIF_CHECKERR(avifDecoderItemAddProperty(colorItem, pixiProp), AVIF_RESULT_OUT_OF_MEMORY);
avifProperty * colrPropNCLX = avifMetaCreateProperty(meta, "colr");
AVIF_CHECKERR(colrPropNCLX, AVIF_RESULT_OUT_OF_MEMORY);
colrPropNCLX->u.colr.hasNCLX = AVIF_TRUE;
colrPropNCLX->u.colr.colorPrimaries = (avifColorPrimaries)colorPrimaries;
colrPropNCLX->u.colr.transferCharacteristics = (avifTransferCharacteristics)transferCharacteristics;
colrPropNCLX->u.colr.matrixCoefficients = (avifMatrixCoefficients)matrixCoefficients;
colrPropNCLX->u.colr.range = fullRange ? AVIF_RANGE_FULL : AVIF_RANGE_LIMITED;
AVIF_CHECKERR(avifDecoderItemAddProperty(colorItem, colrPropNCLX), AVIF_RESULT_OUT_OF_MEMORY);
if (iccDataSize) {
avifProperty * colrPropICC = avifMetaCreateProperty(meta, "colr");
AVIF_CHECKERR(colrPropICC, AVIF_RESULT_OUT_OF_MEMORY);
colrPropICC->u.colr.hasICC = AVIF_TRUE;
colrPropICC->u.colr.iccOffset = rawOffset + avifROStreamOffset(&s);
colrPropICC->u.colr.iccSize = (size_t)iccDataSize;
AVIF_CHECKERR(avifROStreamSkip(&s, colrPropICC->u.colr.iccSize), AVIF_RESULT_BMFF_PARSE_FAILED);
AVIF_CHECKERR(avifDecoderItemAddProperty(colorItem, colrPropICC), AVIF_RESULT_OUT_OF_MEMORY);
} else {
AVIF_CHECKERR(avifMetaCreateProperty(meta, "skip"), AVIF_RESULT_OUT_OF_MEMORY);
}
if (hasAlpha) {
avifProperty * alphaCodecConfigProp = avifMetaCreateProperty(meta, (const char *)codecConfigType);
AVIF_CHECKERR(alphaCodecConfigProp, AVIF_RESULT_OUT_OF_MEMORY);
alphaCodecConfigProp->u.av1C = alphaItemCodecConfig;
AVIF_CHECKERR(avifDecoderItemAddProperty(alphaItem, alphaCodecConfigProp), AVIF_RESULT_OUT_OF_MEMORY);
alphaItem->auxForID = colorItem->id;
colorItem->premByID = alphaIsPremultiplied;
avifProperty * alphaAuxProp = avifMetaCreateProperty(meta, "auxC");
AVIF_CHECKERR(alphaAuxProp, AVIF_RESULT_OUT_OF_MEMORY);
strcpy(alphaAuxProp->u.auxC.auxType, AVIF_URN_ALPHA0);
AVIF_CHECKERR(avifDecoderItemAddProperty(alphaItem, alphaAuxProp), AVIF_RESULT_OUT_OF_MEMORY);
AVIF_CHECKERR(avifDecoderItemAddProperty(alphaItem, ispeProp), AVIF_RESULT_OUT_OF_MEMORY);
avifProperty * alphaPixiProp = avifMetaCreateProperty(meta, "pixi");
AVIF_CHECKERR(alphaPixiProp, AVIF_RESULT_OUT_OF_MEMORY);
memcpy(alphaPixiProp->type, "pixi", 4);
alphaPixiProp->u.pixi.planeCount = 1;
alphaPixiProp->u.pixi.planeDepths[0] = (uint8_t)bitDepth;
AVIF_CHECKERR(avifDecoderItemAddProperty(alphaItem, alphaPixiProp), AVIF_RESULT_OUT_OF_MEMORY);
} else {
AVIF_CHECKERR(avifMetaCreateProperty(meta, "skip"), AVIF_RESULT_OUT_OF_MEMORY);
AVIF_CHECKERR(avifMetaCreateProperty(meta, "skip"), AVIF_RESULT_OUT_OF_MEMORY);
AVIF_CHECKERR(avifMetaCreateProperty(meta, "skip"), AVIF_RESULT_OUT_OF_MEMORY);
}
if (orientation == 3 || orientation == 5 || orientation == 6 || orientation == 7 || orientation == 8) {
avifProperty * irotProp = avifMetaCreateProperty(meta, "irot");
AVIF_CHECKERR(irotProp, AVIF_RESULT_OUT_OF_MEMORY);
irotProp->u.irot.angle = orientation == 3 ? 2 : (orientation == 5 || orientation == 8) ? 1 : 3;
AVIF_CHECKERR(avifDecoderItemAddProperty(colorItem, irotProp), AVIF_RESULT_OUT_OF_MEMORY);
} else {
AVIF_CHECKERR(avifMetaCreateProperty(meta, "skip"), AVIF_RESULT_OUT_OF_MEMORY);
}
if (orientation == 2 || orientation == 4 || orientation == 5 || orientation == 7) {
avifProperty * imirProp = avifMetaCreateProperty(meta, "imir");
AVIF_CHECKERR(imirProp, AVIF_RESULT_OUT_OF_MEMORY);
imirProp->u.imir.axis = orientation == 2 ? 1 : 0;
AVIF_CHECKERR(avifDecoderItemAddProperty(colorItem, imirProp), AVIF_RESULT_OUT_OF_MEMORY);
} else {
AVIF_CHECKERR(avifMetaCreateProperty(meta, "skip"), AVIF_RESULT_OUT_OF_MEMORY);
}
for (int i = 11; i <= 29; ++i) {
AVIF_CHECKERR(avifMetaCreateProperty(meta, "skip"), AVIF_RESULT_OUT_OF_MEMORY);
}
if (hasAlpha) {
avifExtent * alphaExtent = (avifExtent *)avifArrayPush(&alphaItem->extents);
AVIF_CHECKERR(alphaExtent, AVIF_RESULT_OUT_OF_MEMORY);
alphaExtent->offset = rawOffset + avifROStreamOffset(&s);
alphaExtent->size = (size_t)alphaItemDataSize;
AVIF_CHECKERR(avifROStreamSkip(&s, alphaExtent->size), AVIF_RESULT_BMFF_PARSE_FAILED);
alphaItem->size = alphaExtent->size;
}
avifExtent * colorExtent = (avifExtent *)avifArrayPush(&colorItem->extents);
AVIF_CHECKERR(colorExtent, AVIF_RESULT_OUT_OF_MEMORY);
colorExtent->offset = rawOffset + avifROStreamOffset(&s);
colorExtent->size = (size_t)mainItemDataSize;
AVIF_CHECKERR(avifROStreamSkip(&s, colorExtent->size), AVIF_RESULT_BMFF_PARSE_FAILED);
colorItem->size = colorExtent->size;
if (hasExif) {
avifDecoderItem * exifItem;
AVIF_CHECKRES(avifMetaFindOrCreateItem(meta, 3, &exifItem));
memcpy(exifItem->type, "Exif", 4);
exifItem->descForID = colorItem->id;
colorItem->premByID = alphaIsPremultiplied;
avifExtent * exifExtent = (avifExtent *)avifArrayPush(&exifItem->extents);
AVIF_CHECKERR(exifExtent, AVIF_RESULT_OUT_OF_MEMORY);
exifExtent->offset = rawOffset + avifROStreamOffset(&s);
exifExtent->size = (size_t)exifDataSize;
AVIF_CHECKERR(avifROStreamSkip(&s, exifExtent->size), AVIF_RESULT_BMFF_PARSE_FAILED);
exifItem->size = exifExtent->size;
}
if (hasXmp) {
avifDecoderItem * xmpItem;
AVIF_CHECKRES(avifMetaFindOrCreateItem(meta, 4, &xmpItem));
memcpy(xmpItem->type, "mime", 4);
memcpy(xmpItem->contentType.contentType, AVIF_CONTENT_TYPE_XMP, sizeof(AVIF_CONTENT_TYPE_XMP));
xmpItem->descForID = colorItem->id;
colorItem->premByID = alphaIsPremultiplied;
avifExtent * xmpExtent = (avifExtent *)avifArrayPush(&xmpItem->extents);
AVIF_CHECKERR(xmpExtent, AVIF_RESULT_OUT_OF_MEMORY);
xmpExtent->offset = rawOffset + avifROStreamOffset(&s);
xmpExtent->size = (size_t)xmpDataSize;
AVIF_CHECKERR(avifROStreamSkip(&s, xmpExtent->size), AVIF_RESULT_BMFF_PARSE_FAILED);
xmpItem->size = xmpExtent->size;
}
return AVIF_RESULT_OK;
}
#endif
static avifBool avifParseFileTypeBox(avifFileType * ftyp, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{ … }
static avifBool avifFileTypeHasBrand(avifFileType * ftyp, const char * brand);
static avifBool avifFileTypeIsCompatible(avifFileType * ftyp);
static avifResult avifParse(avifDecoder * decoder)
{ … }
static avifBool avifFileTypeHasBrand(avifFileType * ftyp, const char * brand)
{ … }
static avifBool avifFileTypeIsCompatible(avifFileType * ftyp)
{ … }
avifBool avifPeekCompatibleFileType(const avifROData * input)
{ … }
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
static avifBool avifBrandArrayHasBrand(avifBrandArray * brands, const char * brand)
{ … }
#endif
avifDecoder * avifDecoderCreate(void)
{ … }
static void avifDecoderCleanup(avifDecoder * decoder)
{ … }
void avifDecoderDestroy(avifDecoder * decoder)
{ … }
avifResult avifDecoderSetSource(avifDecoder * decoder, avifDecoderSource source)
{ … }
void avifDecoderSetIO(avifDecoder * decoder, avifIO * io)
{ … }
avifResult avifDecoderSetIOMemory(avifDecoder * decoder, const uint8_t * data, size_t size)
{ … }
avifResult avifDecoderSetIOFile(avifDecoder * decoder, const char * filename)
{ … }
static avifResult avifExtentMerge(avifExtent * dst, const avifExtent * src)
{ … }
avifResult avifDecoderNthImageMaxExtent(const avifDecoder * decoder, uint32_t frameIndex, avifExtent * outExtent)
{ … }
static avifResult avifDecoderPrepareSample(avifDecoder * decoder, avifDecodeSample * sample, size_t partialByteCount)
{ … }
static avifBool avifDecoderItemShouldBeSkipped(const avifDecoderItem * item)
{ … }
avifResult avifDecoderParse(avifDecoder * decoder)
{ … }
static avifResult avifCodecCreateInternal(avifCodecChoice choice, const avifTile * tile, avifDiagnostics * diag, avifCodec ** codec)
{ … }
static avifBool avifTilesCanBeDecodedWithSameCodecInstance(avifDecoderData * data)
{ … }
static avifResult avifDecoderCreateCodecs(avifDecoder * decoder)
{ … }
static avifDecoderItem * avifMetaFindColorItem(avifMeta * meta)
{ … }
static avifBool avifDecoderItemIsAlphaAux(const avifDecoderItem * item, uint32_t colorItemId)
{ … }
static avifResult avifMetaFindAlphaItem(avifMeta * meta,
const avifDecoderItem * colorItem,
const avifTileInfo * colorInfo,
avifDecoderItem ** alphaItem,
avifTileInfo * alphaInfo,
avifBool * isAlphaItemInInput)
{ … }
static avifResult avifReadColorNclxProperty(const avifPropertyArray * properties,
avifColorPrimaries * colorPrimaries,
avifTransferCharacteristics * transferCharacteristics,
avifMatrixCoefficients * matrixCoefficients,
avifRange * yuvRange,
avifBool * cicpSet)
{ … }
static avifResult avifReadColorProperties(avifIO * io,
const avifPropertyArray * properties,
avifRWData * icc,
avifColorPrimaries * colorPrimaries,
avifTransferCharacteristics * transferCharacteristics,
avifMatrixCoefficients * matrixCoefficients,
avifRange * yuvRange,
avifBool * cicpSet)
{ … }
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
static avifResult avifDecoderDataFindToneMappedImageItem(const avifDecoderData * data,
const avifDecoderItem * colorItem,
avifDecoderItem ** toneMappedImageItem,
uint32_t * gainMapItemID)
{ … }
static avifResult avifDecoderFindGainMapItem(const avifDecoder * decoder,
const avifDecoderItem * colorItem,
avifDecoderItem ** toneMappedImageItem,
avifDecoderItem ** gainMapItem,
avifCodecType * gainMapCodecType)
{ … }
static avifResult aviDecoderCheckGainMapProperties(avifDecoder * decoder, const avifPropertyArray * gainMapProperties)
{ … }
#endif
#if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM)
static avifResult avifDecoderDataFindSampleTransformImageItem(avifDecoderData * data, avifDecoderItem ** sampleTransformItem)
{
for (uint32_t itemIndex = 0; itemIndex < data->meta->items.count; ++itemIndex) {
avifDecoderItem * item = data->meta->items.item[itemIndex];
if (!item->size || item->hasUnsupportedEssentialProperty || item->thumbnailForID != 0) {
continue;
}
if (!memcmp(item->type, "sato", 4)) {
*sampleTransformItem = item;
return AVIF_RESULT_OK;
}
}
*sampleTransformItem = NULL;
return AVIF_RESULT_OK;
}
#endif
static avifResult avifDecoderGenerateImageTiles(avifDecoder * decoder, avifTileInfo * info, avifDecoderItem * item, avifItemCategory itemCategory)
{ … }
static avifResult avifReadCodecConfigProperty(avifImage * image, const avifPropertyArray * properties, avifCodecType codecType)
{ … }
avifResult avifDecoderReset(avifDecoder * decoder)
{ … }
static avifResult avifDecoderPrepareTiles(avifDecoder * decoder, uint32_t nextImageIndex, const avifTileInfo * info)
{ … }
static avifResult avifImageLimitedToFullAlpha(avifImage * image)
{ … }
static avifResult avifGetErrorForItemCategory(avifItemCategory itemCategory)
{ … }
static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextImageIndex, avifTileInfo * info)
{ … }
static avifBool avifDecoderDataFrameFullyDecoded(const avifDecoderData * data)
{ … }
#if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM)
static avifResult avifDecoderApplySampleTransform(const avifDecoder * decoder, avifImage * dstImage)
{
if (dstImage->depth != decoder->data->meta->sampleTransformDepth) {
AVIF_ASSERT_OR_RETURN(dstImage->yuvPlanes[0] != NULL);
AVIF_ASSERT_OR_RETURN(dstImage->imageOwnsYUVPlanes);
avifImage * dstImageWithCorrectDepth =
avifImageCreate(dstImage->width, dstImage->height, decoder->data->meta->sampleTransformDepth, dstImage->yuvFormat);
AVIF_CHECKERR(dstImageWithCorrectDepth != NULL, AVIF_RESULT_OUT_OF_MEMORY);
avifResult result =
avifImageAllocatePlanes(dstImageWithCorrectDepth, dstImage->alphaPlane != NULL ? AVIF_PLANES_ALL : AVIF_PLANES_YUV);
if (result == AVIF_RESULT_OK) {
result = avifDecoderApplySampleTransform(decoder, dstImageWithCorrectDepth);
if (result == AVIF_RESULT_OK) {
avifImageFreePlanes(dstImage, AVIF_PLANES_ALL);
dstImage->depth = dstImageWithCorrectDepth->depth;
avifImageStealPlanes(dstImage, dstImageWithCorrectDepth, AVIF_PLANES_ALL);
}
}
avifImageDestroy(dstImageWithCorrectDepth);
return result;
}
for (avifBool alpha = AVIF_FALSE; alpha <= decoder->alphaPresent ? AVIF_TRUE : AVIF_FALSE; ++alpha) {
AVIF_ASSERT_OR_RETURN(decoder->data->sampleTransformNumInputImageItems <= AVIF_SAMPLE_TRANSFORM_MAX_NUM_INPUT_IMAGE_ITEMS);
const avifImage * inputImages[AVIF_SAMPLE_TRANSFORM_MAX_NUM_INPUT_IMAGE_ITEMS];
for (uint32_t i = 0; i < decoder->data->sampleTransformNumInputImageItems; ++i) {
avifItemCategory category = decoder->data->sampleTransformInputImageItems[i];
if (category == AVIF_ITEM_COLOR) {
inputImages[i] = decoder->image;
} else {
AVIF_ASSERT_OR_RETURN(category >= AVIF_ITEM_SAMPLE_TRANSFORM_INPUT_0_COLOR &&
category < AVIF_ITEM_SAMPLE_TRANSFORM_INPUT_0_COLOR +
AVIF_SAMPLE_TRANSFORM_MAX_NUM_EXTRA_INPUT_IMAGE_ITEMS);
if (alpha) {
category += AVIF_SAMPLE_TRANSFORM_MAX_NUM_EXTRA_INPUT_IMAGE_ITEMS;
}
const avifTileInfo * tileInfo = &decoder->data->tileInfos[category];
AVIF_CHECKERR(tileInfo->tileCount == 1, AVIF_RESULT_NOT_IMPLEMENTED);
inputImages[i] = decoder->data->tiles.tile[tileInfo->firstTileIndex].image;
AVIF_ASSERT_OR_RETURN(inputImages[i] != NULL);
}
}
AVIF_CHECKRES(avifImageApplyExpression(dstImage,
AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_32,
&decoder->data->meta->sampleTransformExpression,
decoder->data->sampleTransformNumInputImageItems,
inputImages,
alpha ? AVIF_PLANES_A : AVIF_PLANES_YUV));
}
return AVIF_RESULT_OK;
}
#endif
avifResult avifDecoderNextImage(avifDecoder * decoder)
{ … }
avifResult avifDecoderNthImageTiming(const avifDecoder * decoder, uint32_t frameIndex, avifImageTiming * outTiming)
{ … }
avifResult avifDecoderNthImage(avifDecoder * decoder, uint32_t frameIndex)
{ … }
avifBool avifDecoderIsKeyframe(const avifDecoder * decoder, uint32_t frameIndex)
{ … }
uint32_t avifDecoderNearestKeyframe(const avifDecoder * decoder, uint32_t frameIndex)
{ … }
static uint32_t avifGetDecodedRowCount(const avifDecoder * decoder, const avifTileInfo * info, const avifImage * image)
{ … }
uint32_t avifDecoderDecodedRowCount(const avifDecoder * decoder)
{ … }
avifResult avifDecoderRead(avifDecoder * decoder, avifImage * image)
{ … }
avifResult avifDecoderReadMemory(avifDecoder * decoder, avifImage * image, const uint8_t * data, size_t size)
{ … }
avifResult avifDecoderReadFile(avifDecoder * decoder, avifImage * image, const char * filename)
{ … }