Refactor write.c to use a similar Data/Item design as read.c
* Rename read.c's avifData -> avifDecoderData and all associated funcs (disambiguity)
* Rename read.c's struct avifItem -> struct avifDecoderItem (disambiguity)
* Rename read.c's avifDataNewTile() -> avifDataCreateTile() (consistency)
diff --git a/src/read.c b/src/read.c
index d1605b5..3c9abfe 100644
--- a/src/read.c
+++ b/src/read.c
@@ -74,8 +74,8 @@
// ---------------------------------------------------------------------------
// Top-level structures
-// one "item" worth (all iref, iloc, iprp, etc refer to one of these)
-typedef struct avifItem
+// one "item" worth for decoding (all iref, iloc, iprp, etc refer to one of these)
+typedef struct avifDecoderItem
{
uint32_t id;
uint8_t type[4];
@@ -103,10 +103,10 @@
uint32_t auxForID; // if non-zero, this item is an auxC plane for Item #{auxForID}
uint32_t descForID; // if non-zero, this item is a content description for Item #{descForID}
uint32_t dimgForID; // if non-zero, this item is a derived image for Item #{dimgForID}
-} avifItem;
-AVIF_ARRAY_DECLARE(avifItemArray, avifItem, item);
+} avifDecoderItem;
+AVIF_ARRAY_DECLARE(avifDecoderItemArray, avifDecoderItem, item);
-// Temporary storage for ipco contents until they can be associated and memcpy'd to an avifItem
+// Temporary storage for ipco contents until they can be associated and memcpy'd to an avifDecoderItem
typedef struct avifProperty
{
uint8_t type[4];
@@ -122,12 +122,12 @@
AVIF_ARRAY_DECLARE(avifPropertyArray, avifProperty, prop);
// idat storage
-typedef struct avifItemData
+typedef struct avifDecoderItemData
{
uint32_t id;
avifROData data;
-} avifItemData;
-AVIF_ARRAY_DECLARE(avifItemDataArray, avifItemData, idat);
+} avifDecoderItemData;
+AVIF_ARRAY_DECLARE(avifDecoderItemDataArray, avifDecoderItemData, idat);
// grid storage
typedef struct avifImageGrid
@@ -355,7 +355,7 @@
}
// ---------------------------------------------------------------------------
-// avifData
+// avifDecoderData
typedef struct avifTile
{
@@ -365,12 +365,12 @@
} avifTile;
AVIF_ARRAY_DECLARE(avifTileArray, avifTile, tile);
-typedef struct avifData
+typedef struct avifDecoderData
{
avifFileType ftyp;
- avifItemArray items;
+ avifDecoderItemArray items;
avifPropertyArray properties;
- avifItemDataArray idats;
+ avifDecoderItemDataArray idats;
avifTrackArray tracks;
avifROData rawInput;
avifTileArray tiles;
@@ -382,21 +382,21 @@
avifSampleTable * sourceSampleTable; // NULL unless (source == AVIF_DECODER_SOURCE_TRACKS), owned by an avifTrack
uint32_t primaryItemID;
uint32_t metaBoxID; // Ever-incrementing ID for tracking which 'meta' box contains an idat, and which idat an iloc might refer to
-} avifData;
+} avifDecoderData;
-static avifData * avifDataCreate()
+static avifDecoderData * avifDecoderDataCreate()
{
- avifData * data = (avifData *)avifAlloc(sizeof(avifData));
- memset(data, 0, sizeof(avifData));
- avifArrayCreate(&data->items, sizeof(avifItem), 8);
+ avifDecoderData * data = (avifDecoderData *)avifAlloc(sizeof(avifDecoderData));
+ memset(data, 0, sizeof(avifDecoderData));
+ avifArrayCreate(&data->items, sizeof(avifDecoderItem), 8);
avifArrayCreate(&data->properties, sizeof(avifProperty), 16);
- avifArrayCreate(&data->idats, sizeof(avifItemData), 1);
+ avifArrayCreate(&data->idats, sizeof(avifDecoderItemData), 1);
avifArrayCreate(&data->tracks, sizeof(avifTrack), 2);
avifArrayCreate(&data->tiles, sizeof(avifTile), 8);
return data;
}
-static void avifDataResetCodec(avifData * data)
+static void avifDecoderDataResetCodec(avifDecoderData * data)
{
for (unsigned int i = 0; i < data->tiles.count; ++i) {
avifTile * tile = &data->tiles.tile[i];
@@ -410,7 +410,7 @@
}
}
-static avifTile * avifDataNewTile(avifData * data)
+static avifTile * avifDecoderDataCreateTile(avifDecoderData * data)
{
avifTile * tile = (avifTile *)avifArrayPushPtr(&data->tiles);
tile->image = avifImageCreateEmpty();
@@ -418,7 +418,7 @@
return tile;
}
-static void avifDataClearTiles(avifData * data)
+static void avifDecoderDataClearTiles(avifDecoderData * data)
{
for (unsigned int i = 0; i < data->tiles.count; ++i) {
avifTile * tile = &data->tiles.tile[i];
@@ -440,7 +440,7 @@
data->alphaTileCount = 0;
}
-static void avifDataDestroy(avifData * data)
+static void avifDecoderDataDestroy(avifDecoderData * data)
{
avifArrayDestroy(&data->items);
avifArrayDestroy(&data->properties);
@@ -451,12 +451,12 @@
}
}
avifArrayDestroy(&data->tracks);
- avifDataClearTiles(data);
+ avifDecoderDataClearTiles(data);
avifArrayDestroy(&data->tiles);
avifFree(data);
}
-static avifItem * avifDataFindItem(avifData * data, uint32_t itemID)
+static avifDecoderItem * avifDecoderDataFindItem(avifDecoderData * data, uint32_t itemID)
{
if (itemID == 0) {
return NULL;
@@ -468,12 +468,12 @@
}
}
- avifItem * item = (avifItem *)avifArrayPushPtr(&data->items);
+ avifDecoderItem * item = (avifDecoderItem *)avifArrayPushPtr(&data->items);
item->id = itemID;
return item;
}
-static const uint8_t * avifDataCalcItemPtr(avifData * data, avifItem * item)
+static const uint8_t * avifDecoderDataCalcItemPtr(avifDecoderData * data, avifDecoderItem * item)
{
avifROData * offsetBuffer = NULL;
if (item->idatID == 0) {
@@ -507,14 +507,14 @@
return offsetBuffer->data + item->offset;
}
-static avifBool avifDataGenerateImageGridTiles(avifData * data, avifImageGrid * grid, avifItem * gridItem, avifBool alpha)
+static avifBool avifDecoderDataGenerateImageGridTiles(avifDecoderData * data, avifImageGrid * grid, avifDecoderItem * gridItem, avifBool alpha)
{
unsigned int tilesRequested = (unsigned int)grid->rows * (unsigned int)grid->columns;
// Count number of dimg for this item, bail out if it doesn't match perfectly
unsigned int tilesAvailable = 0;
for (uint32_t i = 0; i < data->items.count; ++i) {
- avifItem * item = &data->items.item[i];
+ avifDecoderItem * item = &data->items.item[i];
if (item->dimgForID == gridItem->id) {
if (memcmp(item->type, "av01", 4)) {
continue;
@@ -529,15 +529,15 @@
}
for (uint32_t i = 0; i < data->items.count; ++i) {
- avifItem * item = &data->items.item[i];
+ avifDecoderItem * item = &data->items.item[i];
if (item->dimgForID == gridItem->id) {
if (memcmp(item->type, "av01", 4)) {
continue;
}
- avifTile * tile = avifDataNewTile(data);
+ avifTile * tile = avifDecoderDataCreateTile(data);
avifSample * sample = (avifSample *)avifArrayPushPtr(&tile->input->samples);
- sample->data.data = avifDataCalcItemPtr(data, item);
+ sample->data.data = avifDecoderDataCalcItemPtr(data, item);
sample->data.size = item->size;
sample->sync = AVIF_TRUE;
tile->input->alpha = alpha;
@@ -546,12 +546,12 @@
return AVIF_TRUE;
}
-static avifBool avifDataFillImageGrid(avifData * data,
- avifImageGrid * grid,
- avifImage * dstImage,
- unsigned int firstTileIndex,
- unsigned int tileCount,
- avifBool alpha)
+static avifBool avifDecoderDataFillImageGrid(avifDecoderData * data,
+ avifImageGrid * grid,
+ avifImage * dstImage,
+ unsigned int firstTileIndex,
+ unsigned int tileCount,
+ avifBool alpha)
{
if (tileCount == 0) {
return AVIF_FALSE;
@@ -690,7 +690,7 @@
VARNAME##_roData.size = SIZE; \
avifROStreamStart(&VARNAME, &VARNAME##_roData)
-static avifBool avifParseItemLocationBox(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemLocationBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -768,7 +768,7 @@
uint64_t extentLength; // unsigned int(offset_size*8) extent_length;
CHECK(avifROStreamReadUX8(&s, &extentLength, lengthSize));
- avifItem * item = avifDataFindItem(data, itemID);
+ avifDecoderItem * item = avifDecoderDataFindItem(data, itemID);
if (!item) {
return AVIF_FALSE;
}
@@ -817,7 +817,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseImageSpatialExtentsProperty(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParseImageSpatialExtentsProperty(avifDecoderData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
{
BEGIN_STREAM(s, raw, rawLen);
CHECK(avifROStreamReadAndEnforceVersion(&s, 0));
@@ -827,7 +827,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseAuxiliaryTypeProperty(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParseAuxiliaryTypeProperty(avifDecoderData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
{
BEGIN_STREAM(s, raw, rawLen);
CHECK(avifROStreamReadAndEnforceVersion(&s, 0));
@@ -836,7 +836,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseColourInformationBox(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParseColourInformationBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -892,12 +892,12 @@
return AVIF_TRUE;
}
-static avifBool avifParseAV1CodecConfigurationBoxProperty(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParseAV1CodecConfigurationBoxProperty(avifDecoderData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
{
return avifParseAV1CodecConfigurationBox(raw, rawLen, &data->properties.prop[propertyIndex].av1C);
}
-static avifBool avifParsePixelAspectRatioBoxProperty(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParsePixelAspectRatioBoxProperty(avifDecoderData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -907,7 +907,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseCleanApertureBoxProperty(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParseCleanApertureBoxProperty(avifDecoderData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -923,7 +923,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseImageRotationProperty(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParseImageRotationProperty(avifDecoderData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -936,7 +936,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseImageMirrorProperty(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParseImageMirrorProperty(avifDecoderData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -949,7 +949,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseItemPropertyContainerBox(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemPropertyContainerBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -989,7 +989,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseItemPropertyAssociation(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemPropertyAssociation(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1035,7 +1035,7 @@
return AVIF_FALSE;
}
- avifItem * item = avifDataFindItem(data, itemID);
+ avifDecoderItem * item = avifDecoderDataFindItem(data, itemID);
if (!item) {
return AVIF_FALSE;
}
@@ -1073,7 +1073,7 @@
return AVIF_TRUE;
}
-static avifBool avifParsePrimaryItemBox(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParsePrimaryItemBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
if (data->primaryItemID > 0) {
// Illegal to have multiple pitm boxes, bail out
@@ -1095,7 +1095,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseItemDataBox(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemDataBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
uint32_t idatID = data->metaBoxID;
@@ -1107,14 +1107,14 @@
}
int index = avifArrayPushIndex(&data->idats);
- avifItemData * idat = &data->idats.idat[index];
+ avifDecoderItemData * idat = &data->idats.idat[index];
idat->id = idatID;
idat->data.data = raw;
idat->data.size = rawLen;
return AVIF_TRUE;
}
-static avifBool avifParseItemPropertiesBox(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemPropertiesBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1145,7 +1145,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseItemInfoEntry(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemInfoEntry(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1166,7 +1166,7 @@
memset(&contentType, 0, sizeof(contentType));
}
- avifItem * item = avifDataFindItem(data, itemID);
+ avifDecoderItem * item = avifDecoderDataFindItem(data, itemID);
if (!item) {
return AVIF_FALSE;
}
@@ -1176,7 +1176,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseItemInfoBox(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemInfoBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1210,7 +1210,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseItemReferenceBox(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemReferenceBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1251,7 +1251,7 @@
// Read this reference as "{fromID} is a {irefType} for {toID}"
if (fromID && toID) {
- avifItem * item = avifDataFindItem(data, fromID);
+ avifDecoderItem * item = avifDecoderDataFindItem(data, fromID);
if (!item) {
return AVIF_FALSE;
}
@@ -1267,7 +1267,7 @@
}
if (!memcmp(irefHeader.type, "dimg", 4)) {
// derived images refer in the opposite direction
- avifItem * dimg = avifDataFindItem(data, toID);
+ avifDecoderItem * dimg = avifDecoderDataFindItem(data, toID);
if (!dimg) {
return AVIF_FALSE;
}
@@ -1281,7 +1281,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseMetaBox(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseMetaBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1312,7 +1312,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseTrackHeaderBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseTrackHeaderBox(avifDecoderData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
(void)data;
@@ -1362,7 +1362,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseMediaHeaderBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseMediaHeaderBox(avifDecoderData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
(void)data;
@@ -1394,7 +1394,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseChunkOffsetBox(avifData * data, avifSampleTable * sampleTable, avifBool largeOffsets, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseChunkOffsetBox(avifDecoderData * data, avifSampleTable * sampleTable, avifBool largeOffsets, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
(void)data;
@@ -1419,7 +1419,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseSampleToChunkBox(avifData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseSampleToChunkBox(avifDecoderData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
(void)data;
@@ -1437,7 +1437,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseSampleSizeBox(avifData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseSampleSizeBox(avifDecoderData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
(void)data;
@@ -1459,7 +1459,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseSyncSampleBox(avifData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseSyncSampleBox(avifDecoderData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
(void)data;
@@ -1478,7 +1478,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseTimeToSampleBox(avifData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseTimeToSampleBox(avifDecoderData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
(void)data;
@@ -1496,7 +1496,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseSampleDescriptionBox(avifData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseSampleDescriptionBox(avifDecoderData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
(void)data;
@@ -1533,7 +1533,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseSampleTableBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseSampleTableBox(avifDecoderData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
{
if (track->sampleTable) {
// A TrackBox may only have one SampleTable
@@ -1568,7 +1568,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseMediaInformationBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseMediaInformationBox(avifDecoderData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1585,7 +1585,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseMediaBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseMediaBox(avifDecoderData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1604,7 +1604,7 @@
return AVIF_TRUE;
}
-static avifBool avifTrackReferenceBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
+static avifBool avifTrackReferenceBox(avifDecoderData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
(void)data;
@@ -1625,7 +1625,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseTrackBox(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseTrackBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1648,7 +1648,7 @@
return AVIF_TRUE;
}
-static avifBool avifParseMoovBox(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParseMoovBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1686,7 +1686,7 @@
return AVIF_TRUE;
}
-static avifBool avifParse(avifData * data, const uint8_t * raw, size_t rawLen)
+static avifBool avifParse(avifDecoderData * data, const uint8_t * raw, size_t rawLen)
{
BEGIN_STREAM(s, raw, rawLen);
@@ -1769,7 +1769,7 @@
static void avifDecoderCleanup(avifDecoder * decoder)
{
if (decoder->data) {
- avifDataDestroy(decoder->data);
+ avifDecoderDataDestroy(decoder->data);
decoder->data = NULL;
}
@@ -1799,7 +1799,7 @@
// -----------------------------------------------------------------------
// Parse BMFF boxes
- decoder->data = avifDataCreate();
+ decoder->data = avifDecoderDataCreate();
// Shallow copy, on purpose
memcpy(&decoder->data->rawInput, rawInput, sizeof(avifROData));
@@ -1815,8 +1815,8 @@
// Sanity check items
for (uint32_t itemIndex = 0; itemIndex < decoder->data->items.count; ++itemIndex) {
- avifItem * item = &decoder->data->items.item[itemIndex];
- const uint8_t * p = avifDataCalcItemPtr(decoder->data, item);
+ avifDecoderItem * item = &decoder->data->items.item[itemIndex];
+ const uint8_t * p = avifDecoderDataCalcItemPtr(decoder->data, item);
if (p == NULL) {
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
@@ -1850,7 +1850,7 @@
static avifResult avifDecoderFlush(avifDecoder * decoder)
{
- avifDataResetCodec(decoder->data);
+ avifDecoderDataResetCodec(decoder->data);
for (unsigned int i = 0; i < decoder->data->tiles.count; ++i) {
avifTile * tile = &decoder->data->tiles.tile[i];
@@ -1867,7 +1867,7 @@
avifResult avifDecoderReset(avifDecoder * decoder)
{
- avifData * data = decoder->data;
+ avifDecoderData * data = decoder->data;
if (!data) {
// Nothing to reset.
return AVIF_RESULT_OK;
@@ -1875,7 +1875,7 @@
memset(&data->colorGrid, 0, sizeof(data->colorGrid));
memset(&data->alphaGrid, 0, sizeof(data->alphaGrid));
- avifDataClearTiles(data);
+ avifDecoderDataClearTiles(data);
// Prepare / cleanup decoded image state
if (!decoder->image) {
@@ -1949,7 +1949,7 @@
alphaTrack = &decoder->data->tracks.track[alphaTrackIndex];
}
- avifTile * colorTile = avifDataNewTile(decoder->data);
+ avifTile * colorTile = avifDecoderDataCreateTile(decoder->data);
if (!avifCodecDecodeInputGetSamples(colorTile->input, colorTrack->sampleTable, &decoder->data->rawInput)) {
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
@@ -1957,7 +1957,7 @@
avifTile * alphaTile = NULL;
if (alphaTrack) {
- alphaTile = avifDataNewTile(decoder->data);
+ alphaTile = avifDecoderDataCreateTile(decoder->data);
if (!avifCodecDecodeInputGetSamples(alphaTile->input, alphaTrack->sampleTable, &decoder->data->rawInput)) {
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
@@ -1990,12 +1990,12 @@
avifROData alphaOBU = AVIF_DATA_EMPTY;
avifROData exifData = AVIF_DATA_EMPTY;
avifROData xmpData = AVIF_DATA_EMPTY;
- avifItem * colorOBUItem = NULL;
- avifItem * alphaOBUItem = NULL;
+ avifDecoderItem * colorOBUItem = NULL;
+ avifDecoderItem * alphaOBUItem = NULL;
// Find the colorOBU (primary) item
for (uint32_t itemIndex = 0; itemIndex < data->items.count; ++itemIndex) {
- avifItem * item = &data->items.item[itemIndex];
+ avifDecoderItem * item = &data->items.item[itemIndex];
if (!item->id || !item->size) {
break;
}
@@ -2014,7 +2014,7 @@
}
if (isGrid) {
- const uint8_t * itemPtr = avifDataCalcItemPtr(data, item);
+ const uint8_t * itemPtr = avifDecoderDataCalcItemPtr(data, item);
if (itemPtr == NULL) {
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
@@ -2022,7 +2022,7 @@
return AVIF_RESULT_INVALID_IMAGE_GRID;
}
} else {
- colorOBU.data = avifDataCalcItemPtr(data, item);
+ colorOBU.data = avifDecoderDataCalcItemPtr(data, item);
colorOBU.size = item->size;
}
@@ -2036,7 +2036,7 @@
// Find the alphaOBU item, if any
for (uint32_t itemIndex = 0; itemIndex < data->items.count; ++itemIndex) {
- avifItem * item = &data->items.item[itemIndex];
+ avifDecoderItem * item = &data->items.item[itemIndex];
if (!item->id || !item->size) {
break;
}
@@ -2052,7 +2052,7 @@
if (isAlphaURN(item->auxC.auxType) && (item->auxForID == colorOBUItem->id)) {
if (isGrid) {
- const uint8_t * itemPtr = avifDataCalcItemPtr(data, item);
+ const uint8_t * itemPtr = avifDecoderDataCalcItemPtr(data, item);
if (itemPtr == NULL) {
return AVIF_RESULT_BMFF_PARSE_FAILED;
}
@@ -2060,7 +2060,7 @@
return AVIF_RESULT_INVALID_IMAGE_GRID;
}
} else {
- alphaOBU.data = avifDataCalcItemPtr(data, item);
+ alphaOBU.data = avifDecoderDataCalcItemPtr(data, item);
alphaOBU.size = item->size;
}
@@ -2071,7 +2071,7 @@
// Find Exif and/or XMP metadata, if any
for (uint32_t itemIndex = 0; itemIndex < data->items.count; ++itemIndex) {
- avifItem * item = &data->items.item[itemIndex];
+ avifDecoderItem * item = &data->items.item[itemIndex];
if (!item->id || !item->size) {
break;
}
@@ -2083,7 +2083,7 @@
if (!memcmp(item->type, "Exif", 4)) {
// Advance past Annex A.2.1's header
- const uint8_t * boxPtr = avifDataCalcItemPtr(data, item);
+ const uint8_t * boxPtr = avifDecoderDataCalcItemPtr(data, item);
BEGIN_STREAM(exifBoxStream, boxPtr, item->size);
uint32_t exifTiffHeaderOffset;
CHECK(avifROStreamReadU32(&exifBoxStream, &exifTiffHeaderOffset)); // unsigned int(32) exif_tiff_header_offset;
@@ -2093,13 +2093,13 @@
}
if (!memcmp(item->type, "mime", 4) && !memcmp(item->contentType.contentType, xmpContentType, xmpContentTypeSize)) {
- xmpData.data = avifDataCalcItemPtr(data, item);
+ xmpData.data = avifDecoderDataCalcItemPtr(data, item);
xmpData.size = item->size;
}
}
if ((data->colorGrid.rows > 0) && (data->colorGrid.columns > 0)) {
- if (!avifDataGenerateImageGridTiles(data, &data->colorGrid, colorOBUItem, AVIF_FALSE)) {
+ if (!avifDecoderDataGenerateImageGridTiles(data, &data->colorGrid, colorOBUItem, AVIF_FALSE)) {
return AVIF_RESULT_INVALID_IMAGE_GRID;
}
data->colorTileCount = data->tiles.count;
@@ -2108,7 +2108,7 @@
return AVIF_RESULT_NO_AV1_ITEMS_FOUND;
}
- avifTile * colorTile = avifDataNewTile(decoder->data);
+ avifTile * colorTile = avifDecoderDataCreateTile(decoder->data);
avifSample * colorSample = (avifSample *)avifArrayPushPtr(&colorTile->input->samples);
memcpy(&colorSample->data, &colorOBU, sizeof(avifROData));
colorSample->sync = AVIF_TRUE;
@@ -2116,14 +2116,14 @@
}
if ((data->alphaGrid.rows > 0) && (data->alphaGrid.columns > 0)) {
- if (!avifDataGenerateImageGridTiles(data, &data->alphaGrid, alphaOBUItem, AVIF_FALSE)) {
+ if (!avifDecoderDataGenerateImageGridTiles(data, &data->alphaGrid, alphaOBUItem, AVIF_FALSE)) {
return AVIF_RESULT_INVALID_IMAGE_GRID;
}
data->alphaTileCount = data->tiles.count - data->colorTileCount;
} else {
avifTile * alphaTile = NULL;
if (alphaOBU.size > 0) {
- alphaTile = avifDataNewTile(decoder->data);
+ alphaTile = avifDecoderDataCreateTile(decoder->data);
avifSample * alphaSample = (avifSample *)avifArrayPushPtr(&alphaTile->input->samples);
memcpy(&alphaSample->data, &alphaOBU, sizeof(avifROData));
@@ -2222,7 +2222,8 @@
}
if ((decoder->data->colorGrid.rows > 0) || (decoder->data->colorGrid.columns > 0)) {
- if (!avifDataFillImageGrid(decoder->data, &decoder->data->colorGrid, decoder->image, 0, decoder->data->colorTileCount, AVIF_FALSE)) {
+ if (!avifDecoderDataFillImageGrid(
+ decoder->data, &decoder->data->colorGrid, decoder->image, 0, decoder->data->colorTileCount, AVIF_FALSE)) {
return AVIF_RESULT_INVALID_IMAGE_GRID;
}
} else {
@@ -2251,7 +2252,7 @@
}
if ((decoder->data->alphaGrid.rows > 0) || (decoder->data->alphaGrid.columns > 0)) {
- if (!avifDataFillImageGrid(
+ if (!avifDecoderDataFillImageGrid(
decoder->data, &decoder->data->alphaGrid, decoder->image, decoder->data->colorTileCount, decoder->data->alphaTileCount, AVIF_TRUE)) {
return AVIF_RESULT_INVALID_IMAGE_GRID;
}
diff --git a/src/write.c b/src/write.c
index c5a7d33..d50436d 100644
--- a/src/write.c
+++ b/src/write.c
@@ -27,6 +27,76 @@
static void fillConfigBox(avifCodec * codec, avifImage * image, avifBool alpha);
static void writeConfigBox(avifRWStream * s, avifCodecConfigurationBox * cfg);
+// ---------------------------------------------------------------------------
+// avifEncoderItem
+
+// one "item" worth for encoder
+typedef struct avifEncoderItem
+{
+ uint16_t id;
+ uint8_t type[4];
+ avifImage * image; // avifImage* to use when encoding or populating ipma for this item (unowned)
+ avifCodec * codec; // only present on type==av01
+ avifRWData content; // OBU data on av01, metadata payload for Exif/XMP
+ avifBool alpha;
+
+ const char * infeName;
+ size_t infeNameSize;
+ const char * infeContentType;
+ size_t infeContentTypeSize;
+ size_t infeOffsetOffset; // Stream offset where infe offset was written, so it can be properly set after mdat is written
+
+ uint16_t irefToID; // if non-zero, make an iref from this id -> irefToID
+ const char * irefType;
+
+ struct ipmaArray ipma;
+} avifEncoderItem;
+AVIF_ARRAY_DECLARE(avifEncoderItemArray, avifEncoderItem, item);
+
+// ---------------------------------------------------------------------------
+// avifEncoderData
+
+typedef struct avifEncoderData
+{
+ avifEncoderItemArray items;
+ uint16_t lastItemID;
+ uint16_t primaryItemID;
+} avifEncoderData;
+
+static avifEncoderData * avifEncoderDataCreate()
+{
+ avifEncoderData * data = (avifEncoderData *)avifAlloc(sizeof(avifEncoderData));
+ memset(data, 0, sizeof(avifEncoderData));
+ avifArrayCreate(&data->items, sizeof(avifEncoderItem), 8);
+ return data;
+}
+
+static avifEncoderItem * avifEncoderDataCreateItem(avifEncoderData * data, const char * type, const char * infeName, size_t infeNameSize)
+{
+ avifEncoderItem * item = (avifEncoderItem *)avifArrayPushPtr(&data->items);
+ ++data->lastItemID;
+ item->id = data->lastItemID;
+ memcpy(item->type, type, sizeof(item->type));
+ item->infeName = infeName;
+ item->infeNameSize = infeNameSize;
+ return item;
+}
+
+static void avifEncoderDataDestroy(avifEncoderData * data)
+{
+ for (uint32_t i = 0; i < data->items.count; ++i) {
+ avifEncoderItem * item = &data->items.item[i];
+ if (item->codec) {
+ avifCodecDestroy(item->codec);
+ }
+ avifRWDataFree(&item->content);
+ }
+ avifArrayDestroy(&data->items);
+ avifFree(data);
+}
+
+// ---------------------------------------------------------------------------
+
avifEncoder * avifEncoderCreate(void)
{
avifEncoder * encoder = (avifEncoder *)avifAlloc(sizeof(avifEncoder));
@@ -39,11 +109,13 @@
encoder->tileRowsLog2 = 0;
encoder->tileColsLog2 = 0;
encoder->speed = AVIF_SPEED_DEFAULT;
+ encoder->data = avifEncoderDataCreate();
return encoder;
}
void avifEncoderDestroy(avifEncoder * encoder)
{
+ avifEncoderDataDestroy(encoder->data);
avifFree(encoder);
}
@@ -54,59 +126,86 @@
}
avifResult result = AVIF_RESULT_UNKNOWN_ERROR;
- avifRWData colorOBU = AVIF_DATA_EMPTY;
- avifRWData alphaOBU = AVIF_DATA_EMPTY;
- avifCodec * codec[AVIF_CODEC_PLANES_COUNT];
- codec[AVIF_CODEC_PLANES_COLOR] = avifCodecCreate(encoder->codecChoice, AVIF_CODEC_FLAG_CAN_ENCODE);
- if (!codec[AVIF_CODEC_PLANES_COLOR]) {
+ avifEncoderItem * colorItem = avifEncoderDataCreateItem(encoder->data, "av01", "Color", 6);
+ colorItem->image = image;
+ colorItem->codec = avifCodecCreate(encoder->codecChoice, AVIF_CODEC_FLAG_CAN_ENCODE);
+ if (!colorItem->codec) {
// Just bail out early, we're not surviving this function without an encoder compiled in
return AVIF_RESULT_NO_CODEC_AVAILABLE;
}
+ encoder->data->primaryItemID = colorItem->id;
avifBool imageIsOpaque = avifImageIsOpaque(image);
- if (imageIsOpaque) {
- codec[AVIF_CODEC_PLANES_ALPHA] = NULL;
- } else {
- codec[AVIF_CODEC_PLANES_ALPHA] = avifCodecCreate(encoder->codecChoice, AVIF_CODEC_FLAG_CAN_ENCODE);
- if (!codec[AVIF_CODEC_PLANES_ALPHA]) {
+ if (!imageIsOpaque) {
+ avifEncoderItem * alphaItem = avifEncoderDataCreateItem(encoder->data, "av01", "Alpha", 6);
+ alphaItem->image = image;
+ alphaItem->codec = avifCodecCreate(encoder->codecChoice, AVIF_CODEC_FLAG_CAN_ENCODE);
+ if (!alphaItem->codec) {
return AVIF_RESULT_NO_CODEC_AVAILABLE;
}
+ alphaItem->alpha = AVIF_TRUE;
+ alphaItem->irefToID = encoder->data->primaryItemID;
+ alphaItem->irefType = "auxl";
}
// -----------------------------------------------------------------------
- // Validate Exif payload (if any) and find TIFF header offset
+ // Create metadata items (Exif, XMP)
- uint32_t exifTiffHeaderOffset = 0;
if (image->exif.size > 0) {
- if (image->exif.size < 4) {
- // Can't even fit the TIFF header, something is wrong
- return AVIF_RESULT_INVALID_EXIF_PAYLOAD;
- }
-
- const uint8_t tiffHeaderBE[4] = { 'M', 'M', 0, 42 };
- const uint8_t tiffHeaderLE[4] = { 'I', 'I', 42, 0 };
- for (; exifTiffHeaderOffset < (image->exif.size - 4); ++exifTiffHeaderOffset) {
- if (!memcmp(&image->exif.data[exifTiffHeaderOffset], tiffHeaderBE, sizeof(tiffHeaderBE))) {
- break;
+ // Validate Exif payload (if any) and find TIFF header offset
+ uint32_t exifTiffHeaderOffset = 0;
+ if (image->exif.size > 0) {
+ if (image->exif.size < 4) {
+ // Can't even fit the TIFF header, something is wrong
+ return AVIF_RESULT_INVALID_EXIF_PAYLOAD;
}
- if (!memcmp(&image->exif.data[exifTiffHeaderOffset], tiffHeaderLE, sizeof(tiffHeaderLE))) {
- break;
+
+ const uint8_t tiffHeaderBE[4] = { 'M', 'M', 0, 42 };
+ const uint8_t tiffHeaderLE[4] = { 'I', 'I', 42, 0 };
+ for (; exifTiffHeaderOffset < (image->exif.size - 4); ++exifTiffHeaderOffset) {
+ if (!memcmp(&image->exif.data[exifTiffHeaderOffset], tiffHeaderBE, sizeof(tiffHeaderBE))) {
+ break;
+ }
+ if (!memcmp(&image->exif.data[exifTiffHeaderOffset], tiffHeaderLE, sizeof(tiffHeaderLE))) {
+ break;
+ }
+ }
+
+ if (exifTiffHeaderOffset >= image->exif.size - 4) {
+ // Couldn't find the TIFF header
+ return AVIF_RESULT_INVALID_EXIF_PAYLOAD;
}
}
- if (exifTiffHeaderOffset >= image->exif.size - 4) {
- // Couldn't find the TIFF header
- return AVIF_RESULT_INVALID_EXIF_PAYLOAD;
- }
+ avifEncoderItem * exifItem = avifEncoderDataCreateItem(encoder->data, "Exif", "Exif", 5);
+ exifItem->irefToID = encoder->data->primaryItemID;
+ exifItem->irefType = "cdsc";
+
+ avifRWDataRealloc(&exifItem->content, sizeof(uint32_t) + image->exif.size);
+ exifTiffHeaderOffset = avifHTONL(exifTiffHeaderOffset);
+ memcpy(exifItem->content.data, &exifTiffHeaderOffset, sizeof(uint32_t));
+ memcpy(exifItem->content.data + sizeof(uint32_t), image->exif.data, image->exif.size);
+ }
+
+ if (image->xmp.size > 0) {
+ avifEncoderItem * xmpItem = avifEncoderDataCreateItem(encoder->data, "mime", "XMP", 4);
+ xmpItem->irefToID = encoder->data->primaryItemID;
+ xmpItem->irefType = "cdsc";
+
+ xmpItem->infeContentType = xmpContentType;
+ xmpItem->infeContentTypeSize = xmpContentTypeSize;
+ avifRWDataSet(&xmpItem->content, image->xmp.data, image->xmp.size);
}
// -----------------------------------------------------------------------
// Pre-fill config boxes based on image (codec can query/update later)
- fillConfigBox(codec[AVIF_CODEC_PLANES_COLOR], image, AVIF_FALSE);
- if (codec[AVIF_CODEC_PLANES_ALPHA]) {
- fillConfigBox(codec[AVIF_CODEC_PLANES_ALPHA], image, AVIF_TRUE);
+ for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) {
+ avifEncoderItem * item = &encoder->data->items.item[itemIndex];
+ if (item->codec && item->image) {
+ fillConfigBox(item->codec, item->image, item->alpha);
+ }
}
// -----------------------------------------------------------------------
@@ -131,23 +230,23 @@
// -----------------------------------------------------------------------
// Encode AV1 OBUs
- if (!codec[AVIF_CODEC_PLANES_COLOR]->encodeImage(codec[AVIF_CODEC_PLANES_COLOR], image, encoder, &colorOBU, AVIF_FALSE)) {
- result = AVIF_RESULT_ENCODE_COLOR_FAILED;
- goto writeCleanup;
- }
+ for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) {
+ avifEncoderItem * item = &encoder->data->items.item[itemIndex];
+ if (item->codec && item->image) {
+ if (!item->codec->encodeImage(item->codec, item->image, encoder, &item->content, item->alpha)) {
+ result = item->alpha ? AVIF_RESULT_ENCODE_ALPHA_FAILED : AVIF_RESULT_ENCODE_COLOR_FAILED;
+ goto writeCleanup;
+ }
- if (!imageIsOpaque) {
- if (!codec[AVIF_CODEC_PLANES_ALPHA]->encodeImage(codec[AVIF_CODEC_PLANES_ALPHA], image, encoder, &alphaOBU, AVIF_TRUE)) {
- result = AVIF_RESULT_ENCODE_ALPHA_FAILED;
- goto writeCleanup;
+ // TODO: rethink this if/when image grid encoding support is added
+ if (item->alpha) {
+ encoder->ioStats.alphaOBUSize = item->content.size;
+ } else {
+ encoder->ioStats.colorOBUSize = item->content.size;
+ }
}
}
- // TODO: consider collapsing all items into local structs for iteration / code sharing
- avifBool hasAlpha = (alphaOBU.size > 0);
- avifBool hasExif = (image->exif.size > 0);
- avifBool hasXMP = (image->xmp.size > 0);
-
// -----------------------------------------------------------------------
// Write ftyp
@@ -184,94 +283,31 @@
// -----------------------------------------------------------------------
// Write pitm
- avifRWStreamWriteBox(&s, "pitm", 0, sizeof(uint16_t));
- avifRWStreamWriteU16(&s, 1); // unsigned int(16) item_ID;
-
- // -----------------------------------------------------------------------
- // Calculate item IDs and counts
-
- uint16_t itemCount = 1;
- uint16_t colorItemID = 1;
- uint16_t nextItemID = 2;
- uint16_t alphaItemID = 0;
- uint16_t exifItemID = 0;
- uint16_t xmpItemID = 0;
- if (hasAlpha) {
- ++itemCount;
- alphaItemID = nextItemID;
- ++nextItemID;
- }
- if (hasExif) {
- ++itemCount;
- exifItemID = nextItemID;
- ++nextItemID;
- }
- if (hasXMP) {
- ++itemCount;
- xmpItemID = nextItemID;
- ++nextItemID;
+ if (encoder->data->primaryItemID != 0) {
+ avifRWStreamWriteBox(&s, "pitm", 0, sizeof(uint16_t));
+ avifRWStreamWriteU16(&s, encoder->data->primaryItemID); // unsigned int(16) item_ID;
}
// -----------------------------------------------------------------------
// Write iloc
- // Remember where we want to store the offsets to the mdat OBU offsets to adjust them later.
- // These are named as such because they are remembering the stream offset where we will write an offset later.
- size_t colorOBUOffsetOffset = 0;
- size_t alphaOBUOffsetOffset = 0;
- size_t exifOffsetOffset = 0;
- size_t xmpOffsetOffset = 0;
-
avifBoxMarker iloc = avifRWStreamWriteBox(&s, "iloc", 0, 0);
- // iloc header
- uint8_t offsetSizeAndLengthSize = (4 << 4) + (4 << 0); // unsigned int(4) offset_size;
- // unsigned int(4) length_size;
- avifRWStreamWrite(&s, &offsetSizeAndLengthSize, 1); //
- avifRWStreamWriteZeros(&s, 1); // unsigned int(4) base_offset_size;
- // unsigned int(4) reserved;
- avifRWStreamWriteU16(&s, itemCount); // unsigned int(16) item_count;
+ uint8_t offsetSizeAndLengthSize = (4 << 4) + (4 << 0); // unsigned int(4) offset_size;
+ // unsigned int(4) length_size;
+ avifRWStreamWrite(&s, &offsetSizeAndLengthSize, 1); //
+ avifRWStreamWriteZeros(&s, 1); // unsigned int(4) base_offset_size;
+ // unsigned int(4) reserved;
+ avifRWStreamWriteU16(&s, (uint16_t)encoder->data->items.count); // unsigned int(16) item_count;
- // Item ID #1 (Color OBU)
- avifRWStreamWriteU16(&s, colorItemID); // unsigned int(16) item_ID;
- avifRWStreamWriteU16(&s, 0); // unsigned int(16) data_reference_index;
- avifRWStreamWriteU16(&s, 1); // unsigned int(16) extent_count;
- colorOBUOffsetOffset = avifRWStreamOffset(&s); //
- avifRWStreamWriteU32(&s, 0 /* set later */); // unsigned int(offset_size*8) extent_offset;
- avifRWStreamWriteU32(&s, (uint32_t)colorOBU.size); // unsigned int(length_size*8) extent_length;
-
- if (hasAlpha) {
- avifRWStreamWriteU16(&s, alphaItemID); // unsigned int(16) item_ID;
- avifRWStreamWriteU16(&s, 0); // unsigned int(16) data_reference_index;
- avifRWStreamWriteU16(&s, 1); // unsigned int(16) extent_count;
- alphaOBUOffsetOffset = avifRWStreamOffset(&s); //
- avifRWStreamWriteU32(&s, 0 /* set later */); // unsigned int(offset_size*8) extent_offset;
- avifRWStreamWriteU32(&s, (uint32_t)alphaOBU.size); // unsigned int(length_size*8) extent_length;
- }
-
- if (hasExif) {
- // From ISO/IEC 23008-12:2017
- // :: aligned(8) class ExifDataBlock() {
- // :: unsigned int(32) exif_tiff_header_offset;
- // :: unsigned int(8) exif_payload[];
- // :: }
- uint32_t exifDataBlockSize = (uint32_t)(sizeof(uint32_t) + image->exif.size);
-
- avifRWStreamWriteU16(&s, exifItemID); // unsigned int(16) item_ID;
- avifRWStreamWriteU16(&s, 0); // unsigned int(16) data_reference_index;
- avifRWStreamWriteU16(&s, 1); // unsigned int(16) extent_count;
- exifOffsetOffset = avifRWStreamOffset(&s); //
- avifRWStreamWriteU32(&s, 0 /* set later */); // unsigned int(offset_size*8) extent_offset;
- avifRWStreamWriteU32(&s, exifDataBlockSize); // unsigned int(length_size*8) extent_length;
- }
-
- if (hasXMP) {
- avifRWStreamWriteU16(&s, xmpItemID); // unsigned int(16) item_ID;
- avifRWStreamWriteU16(&s, 0); // unsigned int(16) data_reference_index;
- avifRWStreamWriteU16(&s, 1); // unsigned int(16) extent_count;
- xmpOffsetOffset = avifRWStreamOffset(&s); //
- avifRWStreamWriteU32(&s, 0 /* set later */); // unsigned int(offset_size*8) extent_offset;
- avifRWStreamWriteU32(&s, (uint32_t)image->xmp.size); // unsigned int(length_size*8) extent_length;
+ for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) {
+ avifEncoderItem * item = &encoder->data->items.item[itemIndex];
+ avifRWStreamWriteU16(&s, item->id); // unsigned int(16) item_ID;
+ avifRWStreamWriteU16(&s, 0); // unsigned int(16) data_reference_index;
+ avifRWStreamWriteU16(&s, 1); // unsigned int(16) extent_count;
+ item->infeOffsetOffset = avifRWStreamOffset(&s); //
+ avifRWStreamWriteU32(&s, 0 /* set later */); // unsigned int(offset_size*8) extent_offset;
+ avifRWStreamWriteU32(&s, (uint32_t)item->content.size); // unsigned int(length_size*8) extent_length;
}
avifRWStreamFinishBox(&s, iloc);
@@ -280,216 +316,168 @@
// Write iinf
avifBoxMarker iinf = avifRWStreamWriteBox(&s, "iinf", 0, 0);
- avifRWStreamWriteU16(&s, itemCount); // unsigned int(16) entry_count;
+ avifRWStreamWriteU16(&s, (uint16_t)encoder->data->items.count); // unsigned int(16) entry_count;
- avifBoxMarker infeImage = avifRWStreamWriteBox(&s, "infe", 2, 0);
- avifRWStreamWriteU16(&s, colorItemID); // unsigned int(16) item_ID;
- avifRWStreamWriteU16(&s, 0); // unsigned int(16) item_protection_index;
- avifRWStreamWriteChars(&s, "av01", 4); // unsigned int(32) item_type;
- avifRWStreamWriteChars(&s, "Color", 6); // string item_name; (writing null terminator)
- avifRWStreamFinishBox(&s, infeImage);
- if (hasAlpha) {
- avifBoxMarker infeAlpha = avifRWStreamWriteBox(&s, "infe", 2, 0);
- avifRWStreamWriteU16(&s, alphaItemID); // unsigned int(16) item_ID;
- avifRWStreamWriteU16(&s, 0); // unsigned int(16) item_protection_index;
- avifRWStreamWriteChars(&s, "av01", 4); // unsigned int(32) item_type;
- avifRWStreamWriteChars(&s, "Alpha", 6); // string item_name; (writing null terminator)
- avifRWStreamFinishBox(&s, infeAlpha);
- }
- if (hasExif) {
- avifBoxMarker infeExif = avifRWStreamWriteBox(&s, "infe", 2, 0);
- avifRWStreamWriteU16(&s, exifItemID); // unsigned int(16) item_ID;
- avifRWStreamWriteU16(&s, 0); // unsigned int(16) item_protection_index;
- avifRWStreamWriteChars(&s, "Exif", 4); // unsigned int(32) item_type;
- avifRWStreamWriteChars(&s, "Exif", 5); // string item_name; (writing null terminator)
- avifRWStreamFinishBox(&s, infeExif);
- }
- if (hasXMP) {
- avifBoxMarker infeXMP = avifRWStreamWriteBox(&s, "infe", 2, 0);
- avifRWStreamWriteU16(&s, xmpItemID); // unsigned int(16) item_ID;
+ for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) {
+ avifEncoderItem * item = &encoder->data->items.item[itemIndex];
+
+ avifBoxMarker infe = avifRWStreamWriteBox(&s, "infe", 2, 0);
+ avifRWStreamWriteU16(&s, item->id); // unsigned int(16) item_ID;
avifRWStreamWriteU16(&s, 0); // unsigned int(16) item_protection_index;
- avifRWStreamWriteChars(&s, "mime", 4); // unsigned int(32) item_type;
- avifRWStreamWriteChars(&s, "XMP", 4); // string item_name; (writing null terminator)
- avifRWStreamWriteChars(&s, xmpContentType, xmpContentTypeSize); // string content_type; (writing null terminator)
- avifRWStreamFinishBox(&s, infeXMP);
+ avifRWStreamWrite(&s, item->type, 4); // unsigned int(32) item_type;
+ avifRWStreamWriteChars(&s, item->infeName, item->infeNameSize); // string item_name; (writing null terminator)
+ if (item->infeContentType && item->infeContentTypeSize) { // string content_type; (writing null terminator)
+ avifRWStreamWriteChars(&s, item->infeContentType, item->infeContentTypeSize);
+ }
+ avifRWStreamFinishBox(&s, infe);
}
+
avifRWStreamFinishBox(&s, iinf);
// -----------------------------------------------------------------------
- // Write iref (auxl) for alpha, if any
+ // Write iref boxes
- if (hasAlpha) {
- avifBoxMarker iref = avifRWStreamWriteBox(&s, "iref", 0, 0);
- avifBoxMarker auxl = avifRWStreamWriteBox(&s, "auxl", -1, 0);
- avifRWStreamWriteU16(&s, alphaItemID); // unsigned int(16) from_item_ID;
- avifRWStreamWriteU16(&s, 1); // unsigned int(16) reference_count;
- avifRWStreamWriteU16(&s, colorItemID); // unsigned int(16) to_item_ID;
- avifRWStreamFinishBox(&s, auxl);
- avifRWStreamFinishBox(&s, iref);
+ for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) {
+ avifEncoderItem * item = &encoder->data->items.item[itemIndex];
+ if (item->irefToID != 0) {
+ avifBoxMarker iref = avifRWStreamWriteBox(&s, "iref", 0, 0);
+ avifBoxMarker refType = avifRWStreamWriteBox(&s, item->irefType, -1, 0);
+ avifRWStreamWriteU16(&s, item->id); // unsigned int(16) from_item_ID;
+ avifRWStreamWriteU16(&s, 1); // unsigned int(16) reference_count;
+ avifRWStreamWriteU16(&s, item->irefToID); // unsigned int(16) to_item_ID;
+ avifRWStreamFinishBox(&s, refType);
+ avifRWStreamFinishBox(&s, iref);
+ }
}
// -----------------------------------------------------------------------
- // Write iref (cdsc) for Exif, if any
-
- if (hasExif) {
- avifBoxMarker iref = avifRWStreamWriteBox(&s, "iref", 0, 0);
- avifBoxMarker cdsc = avifRWStreamWriteBox(&s, "cdsc", -1, 0);
- avifRWStreamWriteU16(&s, exifItemID); // unsigned int(16) from_item_ID;
- avifRWStreamWriteU16(&s, 1); // unsigned int(16) reference_count;
- avifRWStreamWriteU16(&s, colorItemID); // unsigned int(16) to_item_ID;
- avifRWStreamFinishBox(&s, cdsc);
- avifRWStreamFinishBox(&s, iref);
- }
-
- // -----------------------------------------------------------------------
- // Write iref (cdsc) for XMP, if any
-
- if (hasXMP) {
- avifBoxMarker iref = avifRWStreamWriteBox(&s, "iref", 0, 0);
- avifBoxMarker cdsc = avifRWStreamWriteBox(&s, "cdsc", -1, 0);
- avifRWStreamWriteU16(&s, xmpItemID); // unsigned int(16) from_item_ID;
- avifRWStreamWriteU16(&s, 1); // unsigned int(16) reference_count;
- avifRWStreamWriteU16(&s, colorItemID); // unsigned int(16) to_item_ID;
- avifRWStreamFinishBox(&s, cdsc);
- avifRWStreamFinishBox(&s, iref);
- }
-
- // -----------------------------------------------------------------------
- // Write iprp->ipco->ispe
+ // Write iprp -> ipco/ipma
avifBoxMarker iprp = avifRWStreamWriteBox(&s, "iprp", -1, 0);
- {
- uint8_t ipcoIndex = 0;
- struct ipmaArray ipmaColor;
- memset(&ipmaColor, 0, sizeof(ipmaColor));
- struct ipmaArray ipmaAlpha;
- memset(&ipmaAlpha, 0, sizeof(ipmaAlpha));
- avifBoxMarker ipco = avifRWStreamWriteBox(&s, "ipco", -1, 0);
- {
- avifBoxMarker ispe = avifRWStreamWriteBox(&s, "ispe", 0, 0);
- avifRWStreamWriteU32(&s, image->width); // unsigned int(32) image_width;
- avifRWStreamWriteU32(&s, image->height); // unsigned int(32) image_height;
- avifRWStreamFinishBox(&s, ispe);
- ++ipcoIndex;
- ipmaPush(&ipmaColor, ipcoIndex); // ipma is 1-indexed, doing this afterwards is correct
- ipmaPush(&ipmaAlpha, ipcoIndex); // Alpha shares the ispe prop
+ uint8_t itemPropertyIndex = 0;
+ avifBoxMarker ipco = avifRWStreamWriteBox(&s, "ipco", -1, 0);
+ for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) {
+ avifEncoderItem * item = &encoder->data->items.item[itemIndex];
+ memset(&item->ipma, 0, sizeof(item->ipma));
+ if (!item->image || !item->codec) {
+ // No ipma to write for this item
+ continue;
+ }
- if (image->profileFormat == AVIF_PROFILE_FORMAT_NCLX) {
+ // Properties all av01 items need
+
+ avifBoxMarker ispe = avifRWStreamWriteBox(&s, "ispe", 0, 0);
+ avifRWStreamWriteU32(&s, item->image->width); // unsigned int(32) image_width;
+ avifRWStreamWriteU32(&s, item->image->height); // unsigned int(32) image_height;
+ avifRWStreamFinishBox(&s, ispe);
+ ipmaPush(&item->ipma, ++itemPropertyIndex); // ipma is 1-indexed, doing this afterwards is correct
+
+ uint8_t channelCount = item->alpha ? 1 : 3; // TODO: write the correct value here when adding monochrome support
+ avifBoxMarker pixi = avifRWStreamWriteBox(&s, "pixi", 0, 0);
+ avifRWStreamWriteU8(&s, channelCount); // unsigned int (8) num_channels;
+ for (uint8_t chan = 0; chan < channelCount; ++chan) {
+ avifRWStreamWriteU8(&s, (uint8_t)item->image->depth); // unsigned int (8) bits_per_channel;
+ }
+ avifRWStreamFinishBox(&s, pixi);
+ ipmaPush(&item->ipma, ++itemPropertyIndex);
+
+ writeConfigBox(&s, &item->codec->configBox);
+ ipmaPush(&item->ipma, ++itemPropertyIndex);
+
+ if (item->alpha) {
+ // Alpha specific properties
+
+ avifBoxMarker auxC = avifRWStreamWriteBox(&s, "auxC", 0, 0);
+ avifRWStreamWriteChars(&s, alphaURN, alphaURNSize); // string aux_type;
+ avifRWStreamFinishBox(&s, auxC);
+ ipmaPush(&item->ipma, ++itemPropertyIndex);
+ } else {
+ // Color specific properties
+
+ if (item->image->profileFormat == AVIF_PROFILE_FORMAT_NCLX) {
avifBoxMarker colr = avifRWStreamWriteBox(&s, "colr", -1, 0);
- avifRWStreamWriteChars(&s, "nclx", 4); // unsigned int(32) colour_type;
- avifRWStreamWriteU16(&s, image->nclx.colourPrimaries); // unsigned int(16) colour_primaries;
- avifRWStreamWriteU16(&s, image->nclx.transferCharacteristics); // unsigned int(16) transfer_characteristics;
- avifRWStreamWriteU16(&s, image->nclx.matrixCoefficients); // unsigned int(16) matrix_coefficients;
- avifRWStreamWriteU8(&s, image->nclx.fullRangeFlag & 0x80); // unsigned int(1) full_range_flag;
- // unsigned int(7) reserved = 0;
+ avifRWStreamWriteChars(&s, "nclx", 4); // unsigned int(32) colour_type;
+ avifRWStreamWriteU16(&s, item->image->nclx.colourPrimaries); // unsigned int(16) colour_primaries;
+ avifRWStreamWriteU16(&s, item->image->nclx.transferCharacteristics); // unsigned int(16) transfer_characteristics;
+ avifRWStreamWriteU16(&s, item->image->nclx.matrixCoefficients); // unsigned int(16) matrix_coefficients;
+ avifRWStreamWriteU8(&s, item->image->nclx.fullRangeFlag & 0x80); // unsigned int(1) full_range_flag;
+ // unsigned int(7) reserved = 0;
avifRWStreamFinishBox(&s, colr);
- ++ipcoIndex;
- ipmaPush(&ipmaColor, ipcoIndex);
- } else if ((image->profileFormat == AVIF_PROFILE_FORMAT_ICC) && image->icc.data && (image->icc.size > 0)) {
+ ipmaPush(&item->ipma, ++itemPropertyIndex);
+ } else if ((item->image->profileFormat == AVIF_PROFILE_FORMAT_ICC) && item->image->icc.data && (item->image->icc.size > 0)) {
avifBoxMarker colr = avifRWStreamWriteBox(&s, "colr", -1, 0);
avifRWStreamWriteChars(&s, "prof", 4); // unsigned int(32) colour_type;
- avifRWStreamWrite(&s, image->icc.data, image->icc.size);
+ avifRWStreamWrite(&s, item->image->icc.data, item->image->icc.size);
avifRWStreamFinishBox(&s, colr);
- ++ipcoIndex;
- ipmaPush(&ipmaColor, ipcoIndex);
+ ipmaPush(&item->ipma, ++itemPropertyIndex);
}
- avifBoxMarker pixiC = avifRWStreamWriteBox(&s, "pixi", 0, 0);
- avifRWStreamWriteU8(&s, 3); // unsigned int (8) num_channels;
- avifRWStreamWriteU8(&s, (uint8_t)image->depth); // unsigned int (8) bits_per_channel;
- avifRWStreamWriteU8(&s, (uint8_t)image->depth); // unsigned int (8) bits_per_channel;
- avifRWStreamWriteU8(&s, (uint8_t)image->depth); // unsigned int (8) bits_per_channel;
- avifRWStreamFinishBox(&s, pixiC);
- ++ipcoIndex;
- ipmaPush(&ipmaColor, ipcoIndex);
-
- writeConfigBox(&s, &codec[AVIF_CODEC_PLANES_COLOR]->configBox);
- ++ipcoIndex;
- ipmaPush(&ipmaColor, ipcoIndex);
-
// Write (Optional) Transformations
- if (image->transformFlags & AVIF_TRANSFORM_PASP) {
+ if (item->image->transformFlags & AVIF_TRANSFORM_PASP) {
avifBoxMarker pasp = avifRWStreamWriteBox(&s, "pasp", -1, 0);
- avifRWStreamWriteU32(&s, image->pasp.hSpacing); // unsigned int(32) hSpacing;
- avifRWStreamWriteU32(&s, image->pasp.vSpacing); // unsigned int(32) vSpacing;
+ avifRWStreamWriteU32(&s, item->image->pasp.hSpacing); // unsigned int(32) hSpacing;
+ avifRWStreamWriteU32(&s, item->image->pasp.vSpacing); // unsigned int(32) vSpacing;
avifRWStreamFinishBox(&s, pasp);
- ++ipcoIndex;
- ipmaPush(&ipmaColor, ipcoIndex);
+ ipmaPush(&item->ipma, ++itemPropertyIndex);
}
- if (image->transformFlags & AVIF_TRANSFORM_CLAP) {
+ if (item->image->transformFlags & AVIF_TRANSFORM_CLAP) {
avifBoxMarker clap = avifRWStreamWriteBox(&s, "clap", -1, 0);
- avifRWStreamWriteU32(&s, image->clap.widthN); // unsigned int(32) cleanApertureWidthN;
- avifRWStreamWriteU32(&s, image->clap.widthD); // unsigned int(32) cleanApertureWidthD;
- avifRWStreamWriteU32(&s, image->clap.heightN); // unsigned int(32) cleanApertureHeightN;
- avifRWStreamWriteU32(&s, image->clap.heightD); // unsigned int(32) cleanApertureHeightD;
- avifRWStreamWriteU32(&s, image->clap.horizOffN); // unsigned int(32) horizOffN;
- avifRWStreamWriteU32(&s, image->clap.horizOffD); // unsigned int(32) horizOffD;
- avifRWStreamWriteU32(&s, image->clap.vertOffN); // unsigned int(32) vertOffN;
- avifRWStreamWriteU32(&s, image->clap.vertOffD); // unsigned int(32) vertOffD;
+ avifRWStreamWriteU32(&s, item->image->clap.widthN); // unsigned int(32) cleanApertureWidthN;
+ avifRWStreamWriteU32(&s, item->image->clap.widthD); // unsigned int(32) cleanApertureWidthD;
+ avifRWStreamWriteU32(&s, item->image->clap.heightN); // unsigned int(32) cleanApertureHeightN;
+ avifRWStreamWriteU32(&s, item->image->clap.heightD); // unsigned int(32) cleanApertureHeightD;
+ avifRWStreamWriteU32(&s, item->image->clap.horizOffN); // unsigned int(32) horizOffN;
+ avifRWStreamWriteU32(&s, item->image->clap.horizOffD); // unsigned int(32) horizOffD;
+ avifRWStreamWriteU32(&s, item->image->clap.vertOffN); // unsigned int(32) vertOffN;
+ avifRWStreamWriteU32(&s, item->image->clap.vertOffD); // unsigned int(32) vertOffD;
avifRWStreamFinishBox(&s, clap);
- ++ipcoIndex;
- ipmaPush(&ipmaColor, ipcoIndex);
+ ipmaPush(&item->ipma, ++itemPropertyIndex);
}
- if (image->transformFlags & AVIF_TRANSFORM_IROT) {
+ if (item->image->transformFlags & AVIF_TRANSFORM_IROT) {
avifBoxMarker irot = avifRWStreamWriteBox(&s, "irot", -1, 0);
- uint8_t angle = image->irot.angle & 0x3;
+ uint8_t angle = item->image->irot.angle & 0x3;
avifRWStreamWrite(&s, &angle, 1); // unsigned int (6) reserved = 0; unsigned int (2) angle;
avifRWStreamFinishBox(&s, irot);
- ++ipcoIndex;
- ipmaPush(&ipmaColor, ipcoIndex);
+ ipmaPush(&item->ipma, ++itemPropertyIndex);
}
- if (image->transformFlags & AVIF_TRANSFORM_IMIR) {
+ if (item->image->transformFlags & AVIF_TRANSFORM_IMIR) {
avifBoxMarker imir = avifRWStreamWriteBox(&s, "imir", -1, 0);
- uint8_t axis = image->imir.axis & 0x1;
+ uint8_t axis = item->image->imir.axis & 0x1;
avifRWStreamWrite(&s, &axis, 1); // unsigned int (7) reserved = 0; unsigned int (1) axis;
avifRWStreamFinishBox(&s, imir);
- ++ipcoIndex;
- ipmaPush(&ipmaColor, ipcoIndex);
- }
-
- if (hasAlpha) {
- avifBoxMarker pixiA = avifRWStreamWriteBox(&s, "pixi", 0, 0);
- avifRWStreamWriteU8(&s, 1); // unsigned int (8) num_channels;
- avifRWStreamWriteU8(&s, (uint8_t)image->depth); // unsigned int (8) bits_per_channel;
- avifRWStreamFinishBox(&s, pixiA);
- ++ipcoIndex;
- ipmaPush(&ipmaAlpha, ipcoIndex);
-
- writeConfigBox(&s, &codec[AVIF_CODEC_PLANES_ALPHA]->configBox);
- ++ipcoIndex;
- ipmaPush(&ipmaAlpha, ipcoIndex);
-
- avifBoxMarker auxC = avifRWStreamWriteBox(&s, "auxC", 0, 0);
- avifRWStreamWriteChars(&s, alphaURN, alphaURNSize); // string aux_type;
- avifRWStreamFinishBox(&s, auxC);
- ++ipcoIndex;
- ipmaPush(&ipmaAlpha, ipcoIndex);
+ ipmaPush(&item->ipma, ++itemPropertyIndex);
}
}
- avifRWStreamFinishBox(&s, ipco);
-
- avifBoxMarker ipma = avifRWStreamWriteBox(&s, "ipma", 0, 0);
- {
- int ipmaCount = hasAlpha ? 2 : 1;
- avifRWStreamWriteU32(&s, ipmaCount); // unsigned int(32) entry_count;
-
- avifRWStreamWriteU16(&s, 1); // unsigned int(16) item_ID;
- avifRWStreamWriteU8(&s, ipmaColor.count); // unsigned int(8) association_count;
- for (int i = 0; i < ipmaColor.count; ++i) { //
- avifRWStreamWriteU8(&s, ipmaColor.associations[i]); // bit(1) essential; unsigned int(7) property_index;
- }
-
- if (hasAlpha) {
- avifRWStreamWriteU16(&s, 2); // unsigned int(16) item_ID;
- avifRWStreamWriteU8(&s, ipmaAlpha.count); // unsigned int(8) association_count;
- for (int i = 0; i < ipmaAlpha.count; ++i) { //
- avifRWStreamWriteU8(&s, ipmaAlpha.associations[i]); // bit(1) essential; unsigned int(7) property_index;
- }
- }
- }
- avifRWStreamFinishBox(&s, ipma);
}
+ avifRWStreamFinishBox(&s, ipco);
+
+ avifBoxMarker ipma = avifRWStreamWriteBox(&s, "ipma", 0, 0);
+ {
+ int ipmaCount = 0;
+ for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) {
+ avifEncoderItem * item = &encoder->data->items.item[itemIndex];
+ if (item->ipma.count > 0) {
+ ++ipmaCount;
+ }
+ }
+ avifRWStreamWriteU32(&s, ipmaCount); // unsigned int(32) entry_count;
+
+ for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) {
+ avifEncoderItem * item = &encoder->data->items.item[itemIndex];
+ if (item->ipma.count == 0) {
+ continue;
+ }
+
+ avifRWStreamWriteU16(&s, item->id); // unsigned int(16) item_ID;
+ avifRWStreamWriteU8(&s, item->ipma.count); // unsigned int(8) association_count;
+ for (int i = 0; i < item->ipma.count; ++i) { //
+ avifRWStreamWriteU8(&s, item->ipma.associations[i]); // bit(1) essential; unsigned int(7) property_index;
+ }
+ }
+ }
+ avifRWStreamFinishBox(&s, ipma);
+
avifRWStreamFinishBox(&s, iprp);
// -----------------------------------------------------------------------
@@ -501,65 +489,35 @@
// Write mdat
avifBoxMarker mdat = avifRWStreamWriteBox(&s, "mdat", -1, 0);
- uint32_t colorOBUOffset = (uint32_t)s.offset;
- avifRWStreamWrite(&s, colorOBU.data, colorOBU.size);
- uint32_t alphaOBUOffset = (uint32_t)s.offset;
- avifRWStreamWrite(&s, alphaOBU.data, alphaOBU.size);
- uint32_t exifOffset = (uint32_t)s.offset;
- if (image->exif.size > 0) {
- avifRWStreamWriteU32(&s, (uint32_t)exifTiffHeaderOffset); // unsigned int(32) exif_tiff_header_offset; (Annex A.2.1)
- avifRWStreamWrite(&s, image->exif.data, image->exif.size);
+ for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) {
+ avifEncoderItem * item = &encoder->data->items.item[itemIndex];
+ if (item->content.size == 0) {
+ continue;
+ }
+
+ uint32_t infeOffset = (uint32_t)s.offset;
+ avifRWStreamWrite(&s, item->content.data, item->content.size);
+
+ if (item->infeOffsetOffset != 0) {
+ size_t prevOffset = avifRWStreamOffset(&s);
+ avifRWStreamSetOffset(&s, item->infeOffsetOffset);
+ avifRWStreamWriteU32(&s, infeOffset);
+ avifRWStreamSetOffset(&s, prevOffset);
+ }
}
- uint32_t xmpOffset = (uint32_t)s.offset;
- avifRWStreamWrite(&s, image->xmp.data, image->xmp.size);
avifRWStreamFinishBox(&s, mdat);
// -----------------------------------------------------------------------
// Finish up stream
- // Set offsets needed in meta box based on where we eventually wrote mdat
- size_t prevOffset = avifRWStreamOffset(&s);
- if (colorOBUOffsetOffset != 0) {
- avifRWStreamSetOffset(&s, colorOBUOffsetOffset);
- avifRWStreamWriteU32(&s, colorOBUOffset);
- }
- if (alphaOBUOffsetOffset != 0) {
- avifRWStreamSetOffset(&s, alphaOBUOffsetOffset);
- avifRWStreamWriteU32(&s, alphaOBUOffset);
- }
- if (exifOffsetOffset != 0) {
- avifRWStreamSetOffset(&s, exifOffsetOffset);
- avifRWStreamWriteU32(&s, exifOffset);
- }
- if (xmpOffsetOffset != 0) {
- avifRWStreamSetOffset(&s, xmpOffsetOffset);
- avifRWStreamWriteU32(&s, xmpOffset);
- }
- avifRWStreamSetOffset(&s, prevOffset);
-
- // Close write stream
avifRWStreamFinishWrite(&s);
// -----------------------------------------------------------------------
- // IO stats
-
- encoder->ioStats.colorOBUSize = colorOBU.size;
- encoder->ioStats.alphaOBUSize = alphaOBU.size;
-
- // -----------------------------------------------------------------------
// Set result and cleanup
result = AVIF_RESULT_OK;
writeCleanup:
- if (codec[AVIF_CODEC_PLANES_COLOR]) {
- avifCodecDestroy(codec[AVIF_CODEC_PLANES_COLOR]);
- }
- if (codec[AVIF_CODEC_PLANES_ALPHA]) {
- avifCodecDestroy(codec[AVIF_CODEC_PLANES_ALPHA]);
- }
- avifRWDataFree(&colorOBU);
- avifRWDataFree(&alphaOBU);
return result;
}