Split avifRawData and avifStream into read-only (const) and read/write versions, updated code accordingly
diff --git a/src/avif.c b/src/avif.c
index 4006d35..bd9e8db 100644
--- a/src/avif.c
+++ b/src/avif.c
@@ -188,22 +188,22 @@
 void avifImageDestroy(avifImage * image)
 {
     avifImageFreePlanes(image, AVIF_PLANES_ALL);
-    avifRawDataFree(&image->icc);
+    avifRWDataFree(&image->icc);
     avifFree(image);
 }
 
 void avifImageSetProfileNone(avifImage * image)
 {
     image->profileFormat = AVIF_PROFILE_FORMAT_NONE;
-    avifRawDataFree(&image->icc);
+    avifRWDataFree(&image->icc);
 }
 
-void avifImageSetProfileICC(avifImage * image, uint8_t * icc, size_t iccSize)
+void avifImageSetProfileICC(avifImage * image, const uint8_t * icc, size_t iccSize)
 {
     avifImageSetProfileNone(image);
     if (iccSize) {
         image->profileFormat = AVIF_PROFILE_FORMAT_ICC;
-        avifRawDataSet(&image->icc, icc, iccSize);
+        avifRWDataSet(&image->icc, icc, iccSize);
     }
 }
 
diff --git a/src/codec_aom.c b/src/codec_aom.c
index 44967d5..fd4c9ea 100644
--- a/src/codec_aom.c
+++ b/src/codec_aom.c
@@ -35,7 +35,7 @@
     uint32_t inputSampleIndex;
     aom_image_t * image;
 
-    avifRawData encodedOBU;
+    avifRWData encodedOBU;
     avifCodecConfigurationBox config;
 };
 
@@ -44,7 +44,7 @@
     if (codec->internal->decoderInitialized) {
         aom_codec_destroy(&codec->internal->decoder);
     }
-    avifRawDataFree(&codec->internal->encodedOBU);
+    avifRWDataFree(&codec->internal->encodedOBU);
     avifFree(codec->internal);
 }
 
@@ -83,7 +83,7 @@
             break;
         } else if (codec->internal->inputSampleIndex < codec->decodeInput->samples.count) {
             // Feed another sample
-            avifRawData * sample = &codec->decodeInput->samples.raw[codec->internal->inputSampleIndex];
+            avifROData * sample = &codec->decodeInput->samples.raw[codec->internal->inputSampleIndex];
             ++codec->internal->inputSampleIndex;
             codec->internal->iter = NULL;
             if (aom_codec_decode(&codec->internal->decoder, sample->data, sample->size, NULL)) {
@@ -232,7 +232,7 @@
     return fmt;
 }
 
-static avifBool encodeOBU(avifImage * image, avifBool alphaOnly, avifEncoder * encoder, avifRawData * outputOBU, avifCodecConfigurationBox * outputConfig)
+static avifBool encodeOBU(avifImage * image, avifBool alphaOnly, avifEncoder * encoder, avifRWData * outputOBU, avifCodecConfigurationBox * outputConfig)
 {
     avifBool success = AVIF_FALSE;
     aom_codec_iface_t * encoder_interface = aom_codec_av1_cx();
@@ -399,7 +399,7 @@
         if (pkt == NULL)
             break;
         if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
-            avifRawDataSet(outputOBU, pkt->data.frame.buf, pkt->data.frame.sz);
+            avifRWDataSet(outputOBU, pkt->data.frame.buf, pkt->data.frame.sz);
             success = AVIF_TRUE;
             break;
         }
@@ -410,7 +410,7 @@
     return success;
 }
 
-static avifBool aomCodecEncodeImage(avifCodec * codec, avifImage * image, avifEncoder * encoder, avifRawData * obu, avifBool alpha)
+static avifBool aomCodecEncodeImage(avifCodec * codec, avifImage * image, avifEncoder * encoder, avifRWData * obu, avifBool alpha)
 {
     if (!encodeOBU(image, alpha, encoder, obu, &codec->internal->config)) {
         return AVIF_FALSE;
diff --git a/src/codec_dav1d.c b/src/codec_dav1d.c
index be2090f..4cc2da8 100644
--- a/src/codec_dav1d.c
+++ b/src/codec_dav1d.c
@@ -38,7 +38,7 @@
         dav1d_data_unref(&codec->internal->dav1dData);
 
         if (codec->internal->inputSampleIndex < codec->decodeInput->samples.count) {
-            avifRawData * sample = &codec->decodeInput->samples.raw[codec->internal->inputSampleIndex];
+            avifROData * sample = &codec->decodeInput->samples.raw[codec->internal->inputSampleIndex];
             ++codec->internal->inputSampleIndex;
 
             // OPTIMIZE: Carefully switch this to use dav1d_data_wrap or dav1d_data_wrap_user_data
diff --git a/src/colr.c b/src/colr.c
index 082bc98..498623f 100644
--- a/src/colr.c
+++ b/src/colr.c
@@ -262,19 +262,19 @@
     return XYZ.xyz.y;
 }
 
-static avifBool readXYZ(uint8_t * data, size_t size, float xyz[3])
+static avifBool readXYZ(const uint8_t * data, size_t size, float xyz[3])
 {
-    avifRawData xyzData;
+    avifROData xyzData;
     xyzData.data = data;
     xyzData.size = size;
-    avifStream s;
-    avifStreamStart(&s, &xyzData);
-    CHECK(avifStreamSkip(&s, 8));
+    avifROStream s;
+    avifROStreamStart(&s, &xyzData);
+    CHECK(avifROStreamSkip(&s, 8));
 
     int32_t fixedXYZ[3];
-    CHECK(avifStreamReadU32(&s, (uint32_t *)&fixedXYZ[0]));
-    CHECK(avifStreamReadU32(&s, (uint32_t *)&fixedXYZ[1]));
-    CHECK(avifStreamReadU32(&s, (uint32_t *)&fixedXYZ[2]));
+    CHECK(avifROStreamReadU32(&s, (uint32_t *)&fixedXYZ[0]));
+    CHECK(avifROStreamReadU32(&s, (uint32_t *)&fixedXYZ[1]));
+    CHECK(avifROStreamReadU32(&s, (uint32_t *)&fixedXYZ[2]));
 
     xyz[0] = fixedToFloat(fixedXYZ[0]);
     xyz[1] = fixedToFloat(fixedXYZ[1]);
@@ -282,37 +282,41 @@
     return AVIF_TRUE;
 }
 
-static avifBool readMat3(uint8_t * data, size_t size, gbMat3 * m)
+static avifBool readMat3(const uint8_t * data, size_t size, gbMat3 * m)
 {
-    avifRawData xyzData;
+    avifROData xyzData;
     xyzData.data = data;
     xyzData.size = size;
-    avifStream s;
-    avifStreamStart(&s, &xyzData);
-    CHECK(avifStreamSkip(&s, 8));
+    avifROStream s;
+    avifROStreamStart(&s, &xyzData);
+    CHECK(avifROStreamSkip(&s, 8));
 
     for (int i = 0; i < 9; ++i) {
         int32_t fixedXYZ;
-        CHECK(avifStreamReadU32(&s, (uint32_t *)&fixedXYZ));
+        CHECK(avifROStreamReadU32(&s, (uint32_t *)&fixedXYZ));
         m->e[i] = fixedToFloat(fixedXYZ);
     }
     return AVIF_TRUE;
 }
 
-static avifBool calcYUVInfoFromICC(avifRawData * icc, float coeffs[3])
+static avifBool calcYUVInfoFromICC(const uint8_t * iccData, size_t iccSize, float coeffs[3])
 {
-    avifStream s;
+    avifROData icc;
+    icc.data = iccData;
+    icc.size = iccSize;
+
+    avifROStream s;
+    avifROStreamStart(&s, &icc);
 
     uint8_t iccMajorVersion;
-    avifStreamStart(&s, icc);
-    CHECK(avifStreamSkip(&s, 8)); // skip to version
-    CHECK(avifStreamRead(&s, &iccMajorVersion, 1));
+    CHECK(avifROStreamSkip(&s, 8)); // skip to version
+    CHECK(avifROStreamRead(&s, &iccMajorVersion, 1));
 
-    avifStreamStart(&s, icc);       // start stream over
-    CHECK(avifStreamSkip(&s, 128)); // skip past the ICC header
+    avifROStreamStart(&s, &icc);      // start stream over
+    CHECK(avifROStreamSkip(&s, 128)); // skip past the ICC header
 
     uint32_t tagCount;
-    CHECK(avifStreamReadU32(&s, &tagCount));
+    CHECK(avifROStreamReadU32(&s, &tagCount));
 
     avifBool rXYZPresent = AVIF_FALSE;
     avifBool gXYZPresent = AVIF_FALSE;
@@ -330,26 +334,26 @@
         uint8_t tagSignature[4];
         uint32_t tagOffset;
         uint32_t tagSize;
-        CHECK(avifStreamRead(&s, tagSignature, 4));
-        CHECK(avifStreamReadU32(&s, &tagOffset));
-        CHECK(avifStreamReadU32(&s, &tagSize));
-        if ((tagOffset + tagSize) > icc->size) {
+        CHECK(avifROStreamRead(&s, tagSignature, 4));
+        CHECK(avifROStreamReadU32(&s, &tagOffset));
+        CHECK(avifROStreamReadU32(&s, &tagSize));
+        if ((tagOffset + tagSize) > icc.size) {
             return AVIF_FALSE;
         }
         if (!memcmp(tagSignature, "rXYZ", 4)) {
-            CHECK(readXYZ(icc->data + tagOffset, tagSize, &colorants.e[0]));
+            CHECK(readXYZ(icc.data + tagOffset, tagSize, &colorants.e[0]));
             rXYZPresent = AVIF_TRUE;
         } else if (!memcmp(tagSignature, "gXYZ", 4)) {
-            CHECK(readXYZ(icc->data + tagOffset, tagSize, &colorants.e[3]));
+            CHECK(readXYZ(icc.data + tagOffset, tagSize, &colorants.e[3]));
             gXYZPresent = AVIF_TRUE;
         } else if (!memcmp(tagSignature, "bXYZ", 4)) {
-            CHECK(readXYZ(icc->data + tagOffset, tagSize, &colorants.e[6]));
+            CHECK(readXYZ(icc.data + tagOffset, tagSize, &colorants.e[6]));
             bXYZPresent = AVIF_TRUE;
         } else if (!memcmp(tagSignature, "wtpt", 4)) {
-            CHECK(readXYZ(icc->data + tagOffset, tagSize, &wtpt.e[0]));
+            CHECK(readXYZ(icc.data + tagOffset, tagSize, &wtpt.e[0]));
             wtptPresent = AVIF_TRUE;
         } else if (!memcmp(tagSignature, "chad", 4)) {
-            CHECK(readMat3(icc->data + tagOffset, tagSize, &chad));
+            CHECK(readMat3(icc.data + tagOffset, tagSize, &chad));
             chadPresent = AVIF_TRUE;
         }
     }
@@ -462,7 +466,7 @@
 
     float coeffs[3];
     if ((image->profileFormat == AVIF_PROFILE_FORMAT_ICC) && image->icc.data && image->icc.size) {
-        if (calcYUVInfoFromICC(&image->icc, coeffs)) {
+        if (calcYUVInfoFromICC(image->icc.data, image->icc.size, coeffs)) {
             kr = coeffs[0];
             kg = coeffs[1];
             kb = coeffs[2];
diff --git a/src/rawdata.c b/src/rawdata.c
index 86e7476..afff617 100644
--- a/src/rawdata.c
+++ b/src/rawdata.c
@@ -5,7 +5,7 @@
 
 #include <string.h>
 
-void avifRawDataRealloc(avifRawData * raw, size_t newSize)
+void avifRWDataRealloc(avifRWData * raw, size_t newSize)
 {
     if (raw->size != newSize) {
         uint8_t * old = raw->data;
@@ -20,37 +20,19 @@
     }
 }
 
-void avifRawDataSet(avifRawData * raw, const uint8_t * data, size_t len)
+void avifRWDataSet(avifRWData * raw, const uint8_t * data, size_t len)
 {
     if (len) {
-        avifRawDataRealloc(raw, len);
+        avifRWDataRealloc(raw, len);
         memcpy(raw->data, data, len);
     } else {
         avifFree(raw);
     }
 }
 
-void avifRawDataFree(avifRawData * raw)
+void avifRWDataFree(avifRWData * raw)
 {
     avifFree(raw->data);
     raw->data = NULL;
     raw->size = 0;
 }
-
-void avifRawDataConcat(avifRawData * dst, avifRawData ** srcs, int srcsCount)
-{
-    size_t totalSize = 0;
-    for (int i = 0; i < srcsCount; ++i) {
-        totalSize += srcs[i]->size;
-    }
-
-    avifRawDataRealloc(dst, totalSize);
-
-    uint8_t * p = dst->data;
-    for (int i = 0; i < srcsCount; ++i) {
-        if (srcs[i]->size) {
-            memcpy(p, srcs[i]->data, srcs[i]->size);
-            p += srcs[i]->size;
-        }
-    }
-}
diff --git a/src/read.c b/src/read.c
index 7c16d86..06e87ea 100644
--- a/src/read.c
+++ b/src/read.c
@@ -50,7 +50,7 @@
 typedef struct avifColourInformationBox
 {
     avifProfileFormat format;
-    uint8_t * icc;
+    const uint8_t * icc;
     size_t iccSize;
     avifNclxColorProfile nclx;
 } avifColourInformationBox;
@@ -177,7 +177,7 @@
 {
     avifCodecDecodeInput * decodeInput = (avifCodecDecodeInput *)avifAlloc(sizeof(avifCodecDecodeInput));
     memset(decodeInput, 0, sizeof(avifCodecDecodeInput));
-    avifArrayCreate(&decodeInput->samples, sizeof(avifRawData), 1);
+    avifArrayCreate(&decodeInput->samples, sizeof(avifROData), 1);
     return decodeInput;
 }
 
@@ -187,7 +187,7 @@
     avifFree(decodeInput);
 }
 
-static avifBool avifCodecDecodeInputGetSamples(avifCodecDecodeInput * decodeInput, avifSampleTable * sampleTable, avifRawData * rawInput)
+static avifBool avifCodecDecodeInputGetSamples(avifCodecDecodeInput * decodeInput, avifSampleTable * sampleTable, avifROData * rawInput)
 {
     uint32_t sampleSizeIndex = 0;
     for (uint32_t chunkIndex = 0; chunkIndex < sampleTable->chunks.count; ++chunkIndex) {
@@ -216,7 +216,7 @@
 
             avifSampleTableSampleSize * sampleSize = &sampleTable->sampleSizes.sampleSize[sampleSizeIndex];
 
-            avifRawData * rawSample = (avifRawData *)avifArrayPushPtr(&decodeInput->samples);
+            avifROData * rawSample = (avifROData *)avifArrayPushPtr(&decodeInput->samples);
             rawSample->data = rawInput->data + sampleOffset;
             rawSample->size = sampleSize->size;
 
@@ -240,7 +240,7 @@
     avifItemArray items;
     avifPropertyArray properties;
     avifTrackArray tracks;
-    avifRawData rawInput;
+    avifROData rawInput;
     avifCodecDecodeInput * colorInput;
     avifCodecDecodeInput * alphaInput;
     avifDecoderSource source;
@@ -321,43 +321,43 @@
 // BMFF Parsing
 
 #define BEGIN_STREAM(VARNAME, PTR, SIZE) \
-    avifStream VARNAME;                  \
-    avifRawData VARNAME##_rawData;       \
-    VARNAME##_rawData.data = PTR;        \
-    VARNAME##_rawData.size = SIZE;       \
-    avifStreamStart(&VARNAME, &VARNAME##_rawData)
+    avifROStream VARNAME;                \
+    avifROData VARNAME##_roData;         \
+    VARNAME##_roData.data = PTR;         \
+    VARNAME##_roData.size = SIZE;        \
+    avifROStreamStart(&VARNAME, &VARNAME##_roData)
 
-static avifBool avifParseItemLocationBox(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemLocationBox(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
-    CHECK(avifStreamReadAndEnforceVersion(&s, 0));
+    CHECK(avifROStreamReadAndEnforceVersion(&s, 0));
 
     uint8_t offsetSizeAndLengthSize;
-    CHECK(avifStreamRead(&s, &offsetSizeAndLengthSize, 1));
+    CHECK(avifROStreamRead(&s, &offsetSizeAndLengthSize, 1));
     uint8_t offsetSize = (offsetSizeAndLengthSize >> 4) & 0xf; // unsigned int(4) offset_size;
     uint8_t lengthSize = (offsetSizeAndLengthSize >> 0) & 0xf; // unsigned int(4) length_size;
 
     uint8_t baseOffsetSizeAndReserved;
-    CHECK(avifStreamRead(&s, &baseOffsetSizeAndReserved, 1));
+    CHECK(avifROStreamRead(&s, &baseOffsetSizeAndReserved, 1));
     uint8_t baseOffsetSize = (baseOffsetSizeAndReserved >> 4) & 0xf; // unsigned int(4) base_offset_size;
 
     uint16_t itemCount;
-    CHECK(avifStreamReadU16(&s, &itemCount)); // unsigned int(16) item_count;
+    CHECK(avifROStreamReadU16(&s, &itemCount)); // unsigned int(16) item_count;
     for (int i = 0; i < itemCount; ++i) {
-        uint16_t itemID;                                           // unsigned int(16) item_ID;
-        CHECK(avifStreamReadU16(&s, &itemID));                     //
-        uint16_t dataReferenceIndex;                               // unsigned int(16) data_ref rence_index;
-        CHECK(avifStreamReadU16(&s, &dataReferenceIndex));         //
-        uint64_t baseOffset;                                       // unsigned int(base_offset_size*8) base_offset;
-        CHECK(avifStreamReadUX8(&s, &baseOffset, baseOffsetSize)); //
-        uint16_t extentCount;                                      // unsigned int(16) extent_count;
-        CHECK(avifStreamReadU16(&s, &extentCount));                //
+        uint16_t itemID;                                             // unsigned int(16) item_ID;
+        CHECK(avifROStreamReadU16(&s, &itemID));                     //
+        uint16_t dataReferenceIndex;                                 // unsigned int(16) data_ref rence_index;
+        CHECK(avifROStreamReadU16(&s, &dataReferenceIndex));         //
+        uint64_t baseOffset;                                         // unsigned int(base_offset_size*8) base_offset;
+        CHECK(avifROStreamReadUX8(&s, &baseOffset, baseOffsetSize)); //
+        uint16_t extentCount;                                        // unsigned int(16) extent_count;
+        CHECK(avifROStreamReadU16(&s, &extentCount));                //
         if (extentCount == 1) {
             uint64_t extentOffset; // unsigned int(offset_size*8) extent_offset;
-            CHECK(avifStreamReadUX8(&s, &extentOffset, offsetSize));
+            CHECK(avifROStreamReadUX8(&s, &extentOffset, offsetSize));
             uint64_t extentLength; // unsigned int(offset_size*8) extent_length;
-            CHECK(avifStreamReadUX8(&s, &extentLength, lengthSize));
+            CHECK(avifROStreamReadUX8(&s, &extentLength, lengthSize));
 
             avifItem * item = avifDataFindItem(data, itemID);
             if (!item) {
@@ -374,110 +374,110 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseImageSpatialExtentsProperty(avifData * data, uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParseImageSpatialExtentsProperty(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
 {
     BEGIN_STREAM(s, raw, rawLen);
-    CHECK(avifStreamReadAndEnforceVersion(&s, 0));
+    CHECK(avifROStreamReadAndEnforceVersion(&s, 0));
 
-    CHECK(avifStreamReadU32(&s, &data->properties.prop[propertyIndex].ispe.width));
-    CHECK(avifStreamReadU32(&s, &data->properties.prop[propertyIndex].ispe.height));
+    CHECK(avifROStreamReadU32(&s, &data->properties.prop[propertyIndex].ispe.width));
+    CHECK(avifROStreamReadU32(&s, &data->properties.prop[propertyIndex].ispe.height));
     return AVIF_TRUE;
 }
 
-static avifBool avifParseAuxiliaryTypeProperty(avifData * data, uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParseAuxiliaryTypeProperty(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
 {
     BEGIN_STREAM(s, raw, rawLen);
-    CHECK(avifStreamReadAndEnforceVersion(&s, 0));
+    CHECK(avifROStreamReadAndEnforceVersion(&s, 0));
 
-    CHECK(avifStreamReadString(&s, data->properties.prop[propertyIndex].auxC.auxType, AUXTYPE_SIZE));
+    CHECK(avifROStreamReadString(&s, data->properties.prop[propertyIndex].auxC.auxType, AUXTYPE_SIZE));
     return AVIF_TRUE;
 }
 
-static avifBool avifParseColourInformationBox(avifData * data, uint8_t * raw, size_t rawLen, int propertyIndex)
+static avifBool avifParseColourInformationBox(avifData * data, const uint8_t * raw, size_t rawLen, int propertyIndex)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
     data->properties.prop[propertyIndex].colr.format = AVIF_PROFILE_FORMAT_NONE;
 
     uint8_t colourType[4]; // unsigned int(32) colour_type;
-    CHECK(avifStreamRead(&s, colourType, 4));
+    CHECK(avifROStreamRead(&s, colourType, 4));
     if (!memcmp(colourType, "rICC", 4) || !memcmp(colourType, "prof", 4)) {
         data->properties.prop[propertyIndex].colr.format = AVIF_PROFILE_FORMAT_ICC;
-        data->properties.prop[propertyIndex].colr.icc = avifStreamCurrent(&s);
-        data->properties.prop[propertyIndex].colr.iccSize = avifStreamRemainingBytes(&s);
+        data->properties.prop[propertyIndex].colr.icc = avifROStreamCurrent(&s);
+        data->properties.prop[propertyIndex].colr.iccSize = avifROStreamRemainingBytes(&s);
     } else if (!memcmp(colourType, "nclx", 4)) {
         // unsigned int(16) colour_primaries;
-        CHECK(avifStreamReadU16(&s, &data->properties.prop[propertyIndex].colr.nclx.colourPrimaries));
+        CHECK(avifROStreamReadU16(&s, &data->properties.prop[propertyIndex].colr.nclx.colourPrimaries));
         // unsigned int(16) transfer_characteristics;
-        CHECK(avifStreamReadU16(&s, &data->properties.prop[propertyIndex].colr.nclx.transferCharacteristics));
+        CHECK(avifROStreamReadU16(&s, &data->properties.prop[propertyIndex].colr.nclx.transferCharacteristics));
         // unsigned int(16) matrix_coefficients;
-        CHECK(avifStreamReadU16(&s, &data->properties.prop[propertyIndex].colr.nclx.matrixCoefficients));
+        CHECK(avifROStreamReadU16(&s, &data->properties.prop[propertyIndex].colr.nclx.matrixCoefficients));
         // unsigned int(1) full_range_flag;
         // unsigned int(7) reserved = 0;
-        CHECK(avifStreamRead(&s, &data->properties.prop[propertyIndex].colr.nclx.fullRangeFlag, 1));
+        CHECK(avifROStreamRead(&s, &data->properties.prop[propertyIndex].colr.nclx.fullRangeFlag, 1));
         data->properties.prop[propertyIndex].colr.nclx.fullRangeFlag |= 0x80;
         data->properties.prop[propertyIndex].colr.format = AVIF_PROFILE_FORMAT_NCLX;
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseItemPropertyContainerBox(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemPropertyContainerBox(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader header;
-        CHECK(avifStreamReadBoxHeader(&s, &header));
+        CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         int propertyIndex = avifArrayPushIndex(&data->properties);
         memcpy(data->properties.prop[propertyIndex].type, header.type, 4);
         if (!memcmp(header.type, "ispe", 4)) {
-            CHECK(avifParseImageSpatialExtentsProperty(data, avifStreamCurrent(&s), header.size, propertyIndex));
+            CHECK(avifParseImageSpatialExtentsProperty(data, avifROStreamCurrent(&s), header.size, propertyIndex));
         }
         if (!memcmp(header.type, "auxC", 4)) {
-            CHECK(avifParseAuxiliaryTypeProperty(data, avifStreamCurrent(&s), header.size, propertyIndex));
+            CHECK(avifParseAuxiliaryTypeProperty(data, avifROStreamCurrent(&s), header.size, propertyIndex));
         }
         if (!memcmp(header.type, "colr", 4)) {
-            CHECK(avifParseColourInformationBox(data, avifStreamCurrent(&s), header.size, propertyIndex));
+            CHECK(avifParseColourInformationBox(data, avifROStreamCurrent(&s), header.size, propertyIndex));
         }
 
-        CHECK(avifStreamSkip(&s, header.size));
+        CHECK(avifROStreamSkip(&s, header.size));
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseItemPropertyAssociation(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemPropertyAssociation(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
     uint8_t version;
     uint8_t flags[3];
-    CHECK(avifStreamReadVersionAndFlags(&s, &version, flags));
+    CHECK(avifROStreamReadVersionAndFlags(&s, &version, flags));
     avifBool propertyIndexIsU16 = (flags[2] & 0x1) ? AVIF_TRUE : AVIF_FALSE; // is flags[2] correct?
 
     uint32_t entryCount;
-    CHECK(avifStreamReadU32(&s, &entryCount));
+    CHECK(avifROStreamReadU32(&s, &entryCount));
     for (uint32_t entryIndex = 0; entryIndex < entryCount; ++entryIndex) {
         unsigned int itemID;
         if (version < 1) {
             uint16_t tmp;
-            CHECK(avifStreamReadU16(&s, &tmp));
+            CHECK(avifROStreamReadU16(&s, &tmp));
             itemID = tmp;
         } else {
-            CHECK(avifStreamReadU32(&s, &itemID));
+            CHECK(avifROStreamReadU32(&s, &itemID));
         }
         uint8_t associationCount;
-        CHECK(avifStreamRead(&s, &associationCount, 1));
+        CHECK(avifROStreamRead(&s, &associationCount, 1));
         for (uint8_t associationIndex = 0; associationIndex < associationCount; ++associationIndex) {
             // avifBool essential = AVIF_FALSE; // currently unused
             uint16_t propertyIndex = 0;
             if (propertyIndexIsU16) {
-                CHECK(avifStreamReadU16(&s, &propertyIndex));
+                CHECK(avifROStreamReadU16(&s, &propertyIndex));
                 // essential = (propertyIndex & 0x8000) ? AVIF_TRUE : AVIF_FALSE;
                 propertyIndex &= 0x7fff;
             } else {
                 uint8_t tmp;
-                CHECK(avifStreamRead(&s, &tmp, 1));
+                CHECK(avifROStreamRead(&s, &tmp, 1));
                 // essential = (tmp & 0x80) ? AVIF_TRUE : AVIF_FALSE;
                 propertyIndex = tmp & 0x7f;
             }
@@ -515,49 +515,49 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseItemPropertiesBox(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemPropertiesBox(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
     avifBoxHeader ipcoHeader;
-    CHECK(avifStreamReadBoxHeader(&s, &ipcoHeader));
+    CHECK(avifROStreamReadBoxHeader(&s, &ipcoHeader));
     if (memcmp(ipcoHeader.type, "ipco", 4) != 0) {
         return AVIF_FALSE;
     }
 
     // Read all item properties inside of ItemPropertyContainerBox
-    CHECK(avifParseItemPropertyContainerBox(data, avifStreamCurrent(&s), ipcoHeader.size));
-    CHECK(avifStreamSkip(&s, ipcoHeader.size));
+    CHECK(avifParseItemPropertyContainerBox(data, avifROStreamCurrent(&s), ipcoHeader.size));
+    CHECK(avifROStreamSkip(&s, ipcoHeader.size));
 
     // Now read all ItemPropertyAssociation until the end of the box, and make associations
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader ipmaHeader;
-        CHECK(avifStreamReadBoxHeader(&s, &ipmaHeader));
+        CHECK(avifROStreamReadBoxHeader(&s, &ipmaHeader));
 
         if (!memcmp(ipmaHeader.type, "ipma", 4)) {
-            CHECK(avifParseItemPropertyAssociation(data, avifStreamCurrent(&s), ipmaHeader.size));
+            CHECK(avifParseItemPropertyAssociation(data, avifROStreamCurrent(&s), ipmaHeader.size));
         } else {
             // These must all be type ipma
             return AVIF_FALSE;
         }
 
-        CHECK(avifStreamSkip(&s, ipmaHeader.size));
+        CHECK(avifROStreamSkip(&s, ipmaHeader.size));
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseItemInfoEntry(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemInfoEntry(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
-    CHECK(avifStreamReadAndEnforceVersion(&s, 2)); // TODO: support version > 2? 2+ is required for item_type
+    CHECK(avifROStreamReadAndEnforceVersion(&s, 2)); // TODO: support version > 2? 2+ is required for item_type
 
-    uint16_t itemID;                                    // unsigned int(16) item_ID;
-    CHECK(avifStreamReadU16(&s, &itemID));              //
-    uint16_t itemProtectionIndex;                       // unsigned int(16) item_protection_index;
-    CHECK(avifStreamReadU16(&s, &itemProtectionIndex)); //
-    uint8_t itemType[4];                                // unsigned int(32) item_type;
-    CHECK(avifStreamRead(&s, itemType, 4));             //
+    uint16_t itemID;                                      // unsigned int(16) item_ID;
+    CHECK(avifROStreamReadU16(&s, &itemID));              //
+    uint16_t itemProtectionIndex;                         // unsigned int(16) item_protection_index;
+    CHECK(avifROStreamReadU16(&s, &itemProtectionIndex)); //
+    uint8_t itemType[4];                                  // unsigned int(32) item_type;
+    CHECK(avifROStreamRead(&s, itemType, 4));             //
 
     avifItem * item = avifDataFindItem(data, itemID);
     if (!item) {
@@ -568,74 +568,74 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseItemInfoBox(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemInfoBox(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
     uint8_t version;
-    CHECK(avifStreamReadVersionAndFlags(&s, &version, NULL));
+    CHECK(avifROStreamReadVersionAndFlags(&s, &version, NULL));
     uint32_t entryCount;
     if (version == 0) {
         uint16_t tmp;
-        CHECK(avifStreamReadU16(&s, &tmp)); // unsigned int(16) entry_count;
+        CHECK(avifROStreamReadU16(&s, &tmp)); // unsigned int(16) entry_count;
         entryCount = tmp;
     } else if (version == 1) {
-        CHECK(avifStreamReadU32(&s, &entryCount)); // unsigned int(32) entry_count;
+        CHECK(avifROStreamReadU32(&s, &entryCount)); // unsigned int(32) entry_count;
     } else {
         return AVIF_FALSE;
     }
 
     for (uint32_t entryIndex = 0; entryIndex < entryCount; ++entryIndex) {
         avifBoxHeader infeHeader;
-        CHECK(avifStreamReadBoxHeader(&s, &infeHeader));
+        CHECK(avifROStreamReadBoxHeader(&s, &infeHeader));
 
         if (!memcmp(infeHeader.type, "infe", 4)) {
-            CHECK(avifParseItemInfoEntry(data, avifStreamCurrent(&s), infeHeader.size));
+            CHECK(avifParseItemInfoEntry(data, avifROStreamCurrent(&s), infeHeader.size));
         } else {
             // These must all be type ipma
             return AVIF_FALSE;
         }
 
-        CHECK(avifStreamSkip(&s, infeHeader.size));
+        CHECK(avifROStreamSkip(&s, infeHeader.size));
     }
 
     return AVIF_TRUE;
 }
 
-static avifBool avifParseItemReferenceBox(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParseItemReferenceBox(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
     uint8_t version;
-    CHECK(avifStreamReadVersionAndFlags(&s, &version, NULL));
+    CHECK(avifROStreamReadVersionAndFlags(&s, &version, NULL));
 
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader irefHeader;
-        CHECK(avifStreamReadBoxHeader(&s, &irefHeader));
+        CHECK(avifROStreamReadBoxHeader(&s, &irefHeader));
 
         uint32_t fromID = 0;
         if (version == 0) {
             uint16_t tmp;
-            CHECK(avifStreamReadU16(&s, &tmp)); // unsigned int(16) from_item_ID;
+            CHECK(avifROStreamReadU16(&s, &tmp)); // unsigned int(16) from_item_ID;
             fromID = tmp;
         } else if (version == 1) {
-            CHECK(avifStreamReadU32(&s, &fromID)); // unsigned int(32) from_item_ID;
+            CHECK(avifROStreamReadU32(&s, &fromID)); // unsigned int(32) from_item_ID;
         } else {
             // unsupported iref version, skip it
             break;
         }
 
         uint16_t referenceCount = 0;
-        CHECK(avifStreamReadU16(&s, &referenceCount)); // unsigned int(16) reference_count;
+        CHECK(avifROStreamReadU16(&s, &referenceCount)); // unsigned int(16) reference_count;
 
         for (uint16_t refIndex = 0; refIndex < referenceCount; ++refIndex) {
             uint32_t toID = 0;
             if (version == 0) {
                 uint16_t tmp;
-                CHECK(avifStreamReadU16(&s, &tmp)); // unsigned int(16) to_item_ID;
+                CHECK(avifROStreamReadU16(&s, &tmp)); // unsigned int(16) to_item_ID;
                 toID = tmp;
             } else if (version == 1) {
-                CHECK(avifStreamReadU32(&s, &toID)); // unsigned int(32) to_item_ID;
+                CHECK(avifROStreamReadU32(&s, &toID)); // unsigned int(32) to_item_ID;
             } else {
                 // unsupported iref version, skip it
                 break;
@@ -661,50 +661,50 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseMetaBox(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParseMetaBox(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
-    CHECK(avifStreamReadAndEnforceVersion(&s, 0));
+    CHECK(avifROStreamReadAndEnforceVersion(&s, 0));
 
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader header;
-        CHECK(avifStreamReadBoxHeader(&s, &header));
+        CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         if (!memcmp(header.type, "iloc", 4)) {
-            CHECK(avifParseItemLocationBox(data, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseItemLocationBox(data, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "iprp", 4)) {
-            CHECK(avifParseItemPropertiesBox(data, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseItemPropertiesBox(data, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "iinf", 4)) {
-            CHECK(avifParseItemInfoBox(data, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseItemInfoBox(data, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "iref", 4)) {
-            CHECK(avifParseItemReferenceBox(data, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseItemReferenceBox(data, avifROStreamCurrent(&s), header.size));
         }
 
-        CHECK(avifStreamSkip(&s, header.size));
+        CHECK(avifROStreamSkip(&s, header.size));
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseTrackHeaderBox(avifData * data, avifTrack * track, uint8_t * raw, size_t rawLen)
+static avifBool avifParseTrackHeaderBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
     (void)data;
 
     uint8_t version;
     uint8_t flags[3];
-    CHECK(avifStreamReadVersionAndFlags(&s, &version, flags));
+    CHECK(avifROStreamReadVersionAndFlags(&s, &version, flags));
 
     uint32_t ignored32, trackID;
     uint64_t ignored64;
     if (version == 1) {
-        CHECK(avifStreamReadU64(&s, &ignored64)); // unsigned int(64) creation_time;
-        CHECK(avifStreamReadU64(&s, &ignored64)); // unsigned int(64) modification_time;
-        CHECK(avifStreamReadU32(&s, &trackID));   // unsigned int(32) track_ID;
+        CHECK(avifROStreamReadU64(&s, &ignored64)); // unsigned int(64) creation_time;
+        CHECK(avifROStreamReadU64(&s, &ignored64)); // unsigned int(64) modification_time;
+        CHECK(avifROStreamReadU32(&s, &trackID));   // unsigned int(32) track_ID;
     } else if (version == 0) {
-        CHECK(avifStreamReadU32(&s, &ignored32)); // unsigned int(32) creation_time;
-        CHECK(avifStreamReadU32(&s, &ignored32)); // unsigned int(32) modification_time;
-        CHECK(avifStreamReadU32(&s, &trackID));   // unsigned int(32) track_ID;
+        CHECK(avifROStreamReadU32(&s, &ignored32)); // unsigned int(32) creation_time;
+        CHECK(avifROStreamReadU32(&s, &ignored32)); // unsigned int(32) modification_time;
+        CHECK(avifROStreamReadU32(&s, &trackID));   // unsigned int(32) track_ID;
     } else {
         // Unsupported version
         return AVIF_FALSE;
@@ -716,28 +716,28 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseMediaHeaderBox(avifData * data, avifTrack * track, uint8_t * raw, size_t rawLen)
+static avifBool avifParseMediaHeaderBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
     (void)data;
 
     uint8_t version;
     uint8_t flags[3];
-    CHECK(avifStreamReadVersionAndFlags(&s, &version, flags));
+    CHECK(avifROStreamReadVersionAndFlags(&s, &version, flags));
 
     uint32_t ignored32, mediaTimescale, mediaDuration32;
     uint64_t ignored64, mediaDuration64;
     if (version == 1) {
-        CHECK(avifStreamReadU64(&s, &ignored64));       // unsigned int(64) creation_time;
-        CHECK(avifStreamReadU64(&s, &ignored64));       // unsigned int(64) modification_time;
-        CHECK(avifStreamReadU32(&s, &mediaTimescale));  // unsigned int(32) timescale;
-        CHECK(avifStreamReadU64(&s, &mediaDuration64)); // unsigned int(64) duration;
+        CHECK(avifROStreamReadU64(&s, &ignored64));       // unsigned int(64) creation_time;
+        CHECK(avifROStreamReadU64(&s, &ignored64));       // unsigned int(64) modification_time;
+        CHECK(avifROStreamReadU32(&s, &mediaTimescale));  // unsigned int(32) timescale;
+        CHECK(avifROStreamReadU64(&s, &mediaDuration64)); // unsigned int(64) duration;
         track->mediaDuration = mediaDuration64;
     } else if (version == 0) {
-        CHECK(avifStreamReadU32(&s, &ignored32));       // unsigned int(32) creation_time;
-        CHECK(avifStreamReadU32(&s, &ignored32));       // unsigned int(32) modification_time;
-        CHECK(avifStreamReadU32(&s, &mediaTimescale));  // unsigned int(32) timescale;
-        CHECK(avifStreamReadU32(&s, &mediaDuration32)); // unsigned int(32) duration;
+        CHECK(avifROStreamReadU32(&s, &ignored32));       // unsigned int(32) creation_time;
+        CHECK(avifROStreamReadU32(&s, &ignored32));       // unsigned int(32) modification_time;
+        CHECK(avifROStreamReadU32(&s, &mediaTimescale));  // unsigned int(32) timescale;
+        CHECK(avifROStreamReadU32(&s, &mediaDuration32)); // unsigned int(32) duration;
         track->mediaDuration = (uint64_t)mediaDuration32;
     } else {
         // Unsupported version
@@ -748,22 +748,22 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseChunkOffsetBox(avifData * data, avifSampleTable * sampleTable, avifBool largeOffsets, uint8_t * raw, size_t rawLen)
+static avifBool avifParseChunkOffsetBox(avifData * data, avifSampleTable * sampleTable, avifBool largeOffsets, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
     (void)data;
 
-    CHECK(avifStreamReadAndEnforceVersion(&s, 0));
+    CHECK(avifROStreamReadAndEnforceVersion(&s, 0));
 
     uint32_t entryCount;
-    CHECK(avifStreamReadU32(&s, &entryCount)); // unsigned int(32) entry_count;
+    CHECK(avifROStreamReadU32(&s, &entryCount)); // unsigned int(32) entry_count;
     for (uint32_t i = 0; i < entryCount; ++i) {
         uint64_t offset;
         if (largeOffsets) {
-            CHECK(avifStreamReadU64(&s, &offset)); // unsigned int(32) chunk_offset;
+            CHECK(avifROStreamReadU64(&s, &offset)); // unsigned int(32) chunk_offset;
         } else {
             uint32_t offset32;
-            CHECK(avifStreamReadU32(&s, &offset32)); // unsigned int(32) chunk_offset;
+            CHECK(avifROStreamReadU32(&s, &offset32)); // unsigned int(32) chunk_offset;
             offset = (uint64_t)offset32;
         }
 
@@ -773,39 +773,39 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseSampleToChunkBox(avifData * data, avifSampleTable * sampleTable, uint8_t * raw, size_t rawLen)
+static avifBool avifParseSampleToChunkBox(avifData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
     (void)data;
 
-    CHECK(avifStreamReadAndEnforceVersion(&s, 0));
+    CHECK(avifROStreamReadAndEnforceVersion(&s, 0));
 
     uint32_t entryCount;
-    CHECK(avifStreamReadU32(&s, &entryCount)); // unsigned int(32) entry_count;
+    CHECK(avifROStreamReadU32(&s, &entryCount)); // unsigned int(32) entry_count;
     for (uint32_t i = 0; i < entryCount; ++i) {
         avifSampleTableSampleToChunk * sampleToChunk = (avifSampleTableSampleToChunk *)avifArrayPushPtr(&sampleTable->sampleToChunks);
-        CHECK(avifStreamReadU32(&s, &sampleToChunk->firstChunk));             // unsigned int(32) first_chunk;
-        CHECK(avifStreamReadU32(&s, &sampleToChunk->samplesPerChunk));        // unsigned int(32) samples_per_chunk;
-        CHECK(avifStreamReadU32(&s, &sampleToChunk->sampleDescriptionIndex)); // unsigned int(32) sample_description_index;
+        CHECK(avifROStreamReadU32(&s, &sampleToChunk->firstChunk));             // unsigned int(32) first_chunk;
+        CHECK(avifROStreamReadU32(&s, &sampleToChunk->samplesPerChunk));        // unsigned int(32) samples_per_chunk;
+        CHECK(avifROStreamReadU32(&s, &sampleToChunk->sampleDescriptionIndex)); // unsigned int(32) sample_description_index;
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseSampleSizeBox(avifData * data, avifSampleTable * sampleTable, uint8_t * raw, size_t rawLen)
+static avifBool avifParseSampleSizeBox(avifData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
     (void)data;
 
-    CHECK(avifStreamReadAndEnforceVersion(&s, 0));
+    CHECK(avifROStreamReadAndEnforceVersion(&s, 0));
 
     uint32_t allSamplesSize, entryCount;
-    CHECK(avifStreamReadU32(&s, &allSamplesSize)); // unsigned int(32) sample_size;
-    CHECK(avifStreamReadU32(&s, &entryCount));     // unsigned int(32) entry_count;
+    CHECK(avifROStreamReadU32(&s, &allSamplesSize)); // unsigned int(32) sample_size;
+    CHECK(avifROStreamReadU32(&s, &entryCount));     // unsigned int(32) entry_count;
 
     for (uint32_t i = 0; i < entryCount; ++i) {
         avifSampleTableSampleSize * sampleSize = (avifSampleTableSampleSize *)avifArrayPushPtr(&sampleTable->sampleSizes);
         if (allSamplesSize == 0) {
-            CHECK(avifStreamReadU32(&s, &sampleSize->size)); // unsigned int(32) entry_size;
+            CHECK(avifROStreamReadU32(&s, &sampleSize->size)); // unsigned int(32) entry_size;
         } else {
             // This could be done more efficiently, memory-wise.
             sampleSize->size = allSamplesSize;
@@ -814,25 +814,25 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseTimeToSampleBox(avifData * data, avifSampleTable * sampleTable, uint8_t * raw, size_t rawLen)
+static avifBool avifParseTimeToSampleBox(avifData * data, avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
     (void)data;
 
-    CHECK(avifStreamReadAndEnforceVersion(&s, 0));
+    CHECK(avifROStreamReadAndEnforceVersion(&s, 0));
 
     uint32_t entryCount;
-    CHECK(avifStreamReadU32(&s, &entryCount)); // unsigned int(32) entry_count;
+    CHECK(avifROStreamReadU32(&s, &entryCount)); // unsigned int(32) entry_count;
 
     for (uint32_t i = 0; i < entryCount; ++i) {
         avifSampleTableTimeToSample * timeToSample = (avifSampleTableTimeToSample *)avifArrayPushPtr(&sampleTable->timeToSamples);
-        CHECK(avifStreamReadU32(&s, &timeToSample->sampleCount)); // unsigned int(32) sample_count;
-        CHECK(avifStreamReadU32(&s, &timeToSample->sampleDelta)); // unsigned int(32) sample_delta;
+        CHECK(avifROStreamReadU32(&s, &timeToSample->sampleCount)); // unsigned int(32) sample_count;
+        CHECK(avifROStreamReadU32(&s, &timeToSample->sampleDelta)); // unsigned int(32) sample_delta;
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseSampleTableBox(avifData * data, avifTrack * track, uint8_t * raw, size_t rawLen)
+static avifBool avifParseSampleTableBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
 {
     if (track->sampleTable) {
         // A TrackBox may only have one SampleTable
@@ -842,132 +842,132 @@
 
     BEGIN_STREAM(s, raw, rawLen);
 
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader header;
-        CHECK(avifStreamReadBoxHeader(&s, &header));
+        CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         if (!memcmp(header.type, "stco", 4)) {
-            CHECK(avifParseChunkOffsetBox(data, track->sampleTable, AVIF_FALSE, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseChunkOffsetBox(data, track->sampleTable, AVIF_FALSE, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "co64", 4)) {
-            CHECK(avifParseChunkOffsetBox(data, track->sampleTable, AVIF_TRUE, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseChunkOffsetBox(data, track->sampleTable, AVIF_TRUE, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "stsc", 4)) {
-            CHECK(avifParseSampleToChunkBox(data, track->sampleTable, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseSampleToChunkBox(data, track->sampleTable, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "stsz", 4)) {
-            CHECK(avifParseSampleSizeBox(data, track->sampleTable, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseSampleSizeBox(data, track->sampleTable, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "stts", 4)) {
-            CHECK(avifParseTimeToSampleBox(data, track->sampleTable, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseTimeToSampleBox(data, track->sampleTable, avifROStreamCurrent(&s), header.size));
         }
 
-        CHECK(avifStreamSkip(&s, header.size));
+        CHECK(avifROStreamSkip(&s, header.size));
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseMediaInformationBox(avifData * data, avifTrack * track, uint8_t * raw, size_t rawLen)
+static avifBool avifParseMediaInformationBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader header;
-        CHECK(avifStreamReadBoxHeader(&s, &header));
+        CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         if (!memcmp(header.type, "stbl", 4)) {
-            CHECK(avifParseSampleTableBox(data, track, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseSampleTableBox(data, track, avifROStreamCurrent(&s), header.size));
         }
 
-        CHECK(avifStreamSkip(&s, header.size));
+        CHECK(avifROStreamSkip(&s, header.size));
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseMediaBox(avifData * data, avifTrack * track, uint8_t * raw, size_t rawLen)
+static avifBool avifParseMediaBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader header;
-        CHECK(avifStreamReadBoxHeader(&s, &header));
+        CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         if (!memcmp(header.type, "mdhd", 4)) {
-            CHECK(avifParseMediaHeaderBox(data, track, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseMediaHeaderBox(data, track, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "minf", 4)) {
-            CHECK(avifParseMediaInformationBox(data, track, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseMediaInformationBox(data, track, avifROStreamCurrent(&s), header.size));
         }
 
-        CHECK(avifStreamSkip(&s, header.size));
+        CHECK(avifROStreamSkip(&s, header.size));
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifTrackReferenceBox(avifData * data, avifTrack * track, uint8_t * raw, size_t rawLen)
+static avifBool avifTrackReferenceBox(avifData * data, avifTrack * track, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
     (void)data;
 
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader header;
-        CHECK(avifStreamReadBoxHeader(&s, &header));
+        CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         if (!memcmp(header.type, "auxl", 4)) {
             uint32_t toID;
-            CHECK(avifStreamReadU32(&s, &toID));                       // unsigned int(32) track_IDs[]
-            CHECK(avifStreamSkip(&s, header.size - sizeof(uint32_t))); // just take the first one
+            CHECK(avifROStreamReadU32(&s, &toID));                       // unsigned int(32) track_IDs[]
+            CHECK(avifROStreamSkip(&s, header.size - sizeof(uint32_t))); // just take the first one
             track->auxForID = toID;
         } else {
-            CHECK(avifStreamSkip(&s, header.size));
+            CHECK(avifROStreamSkip(&s, header.size));
         }
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseTrackBox(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParseTrackBox(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
     avifTrack * track = (avifTrack *)avifArrayPushPtr(&data->tracks);
 
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader header;
-        CHECK(avifStreamReadBoxHeader(&s, &header));
+        CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         if (!memcmp(header.type, "tkhd", 4)) {
-            CHECK(avifParseTrackHeaderBox(data, track, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseTrackHeaderBox(data, track, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "mdia", 4)) {
-            CHECK(avifParseMediaBox(data, track, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseMediaBox(data, track, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "tref", 4)) {
-            CHECK(avifTrackReferenceBox(data, track, avifStreamCurrent(&s), header.size));
+            CHECK(avifTrackReferenceBox(data, track, avifROStreamCurrent(&s), header.size));
         }
 
-        CHECK(avifStreamSkip(&s, header.size));
+        CHECK(avifROStreamSkip(&s, header.size));
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseMoovBox(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParseMoovBox(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader header;
-        CHECK(avifStreamReadBoxHeader(&s, &header));
+        CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         if (!memcmp(header.type, "trak", 4)) {
-            CHECK(avifParseTrackBox(data, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseTrackBox(data, avifROStreamCurrent(&s), header.size));
         }
 
-        CHECK(avifStreamSkip(&s, header.size));
+        CHECK(avifROStreamSkip(&s, header.size));
     }
     return AVIF_TRUE;
 }
 
-static avifBool avifParseFileTypeBox(avifFileType * ftyp, uint8_t * raw, size_t rawLen)
+static avifBool avifParseFileTypeBox(avifFileType * ftyp, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
-    CHECK(avifStreamRead(&s, ftyp->majorBrand, 4));
-    CHECK(avifStreamReadU32(&s, &ftyp->minorVersion));
+    CHECK(avifROStreamRead(&s, ftyp->majorBrand, 4));
+    CHECK(avifROStreamReadU32(&s, &ftyp->minorVersion));
 
-    size_t compatibleBrandsBytes = avifStreamRemainingBytes(&s);
+    size_t compatibleBrandsBytes = avifROStreamRemainingBytes(&s);
     if ((compatibleBrandsBytes % 4) != 0) {
         return AVIF_FALSE;
     }
@@ -975,29 +975,29 @@
         // TODO: stop clamping and resize this
         compatibleBrandsBytes = (4 * MAX_COMPATIBLE_BRANDS);
     }
-    CHECK(avifStreamRead(&s, ftyp->compatibleBrands, compatibleBrandsBytes));
+    CHECK(avifROStreamRead(&s, ftyp->compatibleBrands, compatibleBrandsBytes));
     ftyp->compatibleBrandsCount = (int)compatibleBrandsBytes / 4;
 
     return AVIF_TRUE;
 }
 
-static avifBool avifParse(avifData * data, uint8_t * raw, size_t rawLen)
+static avifBool avifParse(avifData * data, const uint8_t * raw, size_t rawLen)
 {
     BEGIN_STREAM(s, raw, rawLen);
 
-    while (avifStreamHasBytesLeft(&s, 1)) {
+    while (avifROStreamHasBytesLeft(&s, 1)) {
         avifBoxHeader header;
-        CHECK(avifStreamReadBoxHeader(&s, &header));
+        CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         if (!memcmp(header.type, "ftyp", 4)) {
-            CHECK(avifParseFileTypeBox(&data->ftyp, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseFileTypeBox(&data->ftyp, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "meta", 4)) {
-            CHECK(avifParseMetaBox(data, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseMetaBox(data, avifROStreamCurrent(&s), header.size));
         } else if (!memcmp(header.type, "moov", 4)) {
-            CHECK(avifParseMoovBox(data, avifStreamCurrent(&s), header.size));
+            CHECK(avifParseMoovBox(data, avifROStreamCurrent(&s), header.size));
         }
 
-        CHECK(avifStreamSkip(&s, header.size));
+        CHECK(avifROStreamSkip(&s, header.size));
     }
     return AVIF_TRUE;
 }
@@ -1026,19 +1026,19 @@
     return avifCompatible;
 }
 
-avifBool avifPeekCompatibleFileType(avifRawData * input)
+avifBool avifPeekCompatibleFileType(avifROData * input)
 {
     BEGIN_STREAM(s, input->data, input->size);
 
     avifBoxHeader header;
-    CHECK(avifStreamReadBoxHeader(&s, &header));
+    CHECK(avifROStreamReadBoxHeader(&s, &header));
     if (memcmp(header.type, "ftyp", 4) != 0) {
         return AVIF_FALSE;
     }
 
     avifFileType ftyp;
     memset(&ftyp, 0, sizeof(avifFileType));
-    avifBool parsed = avifParseFileTypeBox(&ftyp, avifStreamCurrent(&s), header.size);
+    avifBool parsed = avifParseFileTypeBox(&ftyp, avifROStreamCurrent(&s), header.size);
     if (!parsed) {
         return AVIF_FALSE;
     }
@@ -1079,7 +1079,7 @@
     return avifDecoderReset(decoder);
 }
 
-avifResult avifDecoderParse(avifDecoder * decoder, avifRawData * rawInput)
+avifResult avifDecoderParse(avifDecoder * decoder, avifROData * rawInput)
 {
 #if !defined(AVIF_CODEC_AOM) && !defined(AVIF_CODEC_DAV1D)
     // Just bail out early, we're not surviving this function without a decoder compiled in
@@ -1095,7 +1095,7 @@
     decoder->data = avifDataCreate();
 
     // Shallow copy, on purpose
-    memcpy(&decoder->data->rawInput, rawInput, sizeof(avifRawData));
+    memcpy(&decoder->data->rawInput, rawInput, sizeof(avifROData));
 
     if (!avifParse(decoder->data, decoder->data->rawInput.data, decoder->data->rawInput.size)) {
         return AVIF_RESULT_BMFF_PARSE_FAILED;
@@ -1256,8 +1256,8 @@
     } else {
         // Create from items
 
-        avifRawData colorOBU = AVIF_RAW_DATA_EMPTY;
-        avifRawData alphaOBU = AVIF_RAW_DATA_EMPTY;
+        avifROData colorOBU = AVIF_DATA_EMPTY;
+        avifROData alphaOBU = AVIF_DATA_EMPTY;
         avifItem * colorOBUItem = NULL;
 
         // Find the colorOBU item
@@ -1318,12 +1318,12 @@
         }
 
         data->colorInput = avifCodecDecodeInputCreate();
-        avifRawData * rawColorInput = (avifRawData *)avifArrayPushPtr(&data->colorInput->samples);
-        memcpy(rawColorInput, &colorOBU, sizeof(avifRawData));
+        avifROData * rawColorInput = (avifROData *)avifArrayPushPtr(&data->colorInput->samples);
+        memcpy(rawColorInput, &colorOBU, sizeof(avifROData));
         if (alphaOBU.size > 0) {
             data->alphaInput = avifCodecDecodeInputCreate();
-            avifRawData * rawAlphaInput = (avifRawData *)avifArrayPushPtr(&data->alphaInput->samples);
-            memcpy(rawAlphaInput, &alphaOBU, sizeof(avifRawData));
+            avifROData * rawAlphaInput = (avifROData *)avifArrayPushPtr(&data->alphaInput->samples);
+            memcpy(rawAlphaInput, &alphaOBU, sizeof(avifROData));
             data->alphaInput->alpha = AVIF_TRUE;
         }
 
@@ -1418,7 +1418,7 @@
     return AVIF_RESULT_OK;
 }
 
-avifResult avifDecoderRead(avifDecoder * decoder, avifImage * image, avifRawData * input)
+avifResult avifDecoderRead(avifDecoder * decoder, avifImage * image, avifROData * input)
 {
     avifResult result = avifDecoderParse(decoder, input);
     if (result != AVIF_RESULT_OK) {
diff --git a/src/stream.c b/src/stream.c
index 8eb7edc..ce76329 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -5,36 +5,36 @@
 
 #include <string.h>
 
-uint8_t * avifStreamCurrent(avifStream * stream)
+// ---------------------------------------------------------------------------
+// avifROStream
+
+const uint8_t * avifROStreamCurrent(avifROStream * stream)
 {
     return stream->raw->data + stream->offset;
 }
 
-void avifStreamStart(avifStream * stream, avifRawData * raw)
+void avifROStreamStart(avifROStream * stream, avifROData * raw)
 {
     stream->raw = raw;
     stream->offset = 0;
 }
 
-// ---------------------------------------------------------------------------
-// Read
-
-avifBool avifStreamHasBytesLeft(avifStream * stream, size_t byteCount)
+avifBool avifROStreamHasBytesLeft(avifROStream * stream, size_t byteCount)
 {
     return (stream->offset + byteCount) <= stream->raw->size;
 }
 
-size_t avifStreamRemainingBytes(avifStream * stream)
+size_t avifROStreamRemainingBytes(avifROStream * stream)
 {
     return stream->raw->size - stream->offset;
 }
 
-size_t avifStreamOffset(avifStream * stream)
+size_t avifROStreamOffset(avifROStream * stream)
 {
     return stream->offset;
 }
 
-void avifStreamSetOffset(avifStream * stream, size_t offset)
+void avifROStreamSetOffset(avifROStream * stream, size_t offset)
 {
     stream->offset = offset;
     if (stream->offset > stream->raw->size) {
@@ -42,18 +42,18 @@
     }
 }
 
-avifBool avifStreamSkip(avifStream * stream, size_t byteCount)
+avifBool avifROStreamSkip(avifROStream * stream, size_t byteCount)
 {
-    if (!avifStreamHasBytesLeft(stream, byteCount)) {
+    if (!avifROStreamHasBytesLeft(stream, byteCount)) {
         return AVIF_FALSE;
     }
     stream->offset += byteCount;
     return AVIF_TRUE;
 }
 
-avifBool avifStreamRead(avifStream * stream, uint8_t * data, size_t size)
+avifBool avifROStreamRead(avifROStream * stream, uint8_t * data, size_t size)
 {
-    if (!avifStreamHasBytesLeft(stream, size)) {
+    if (!avifROStreamHasBytesLeft(stream, size)) {
         return AVIF_FALSE;
     }
 
@@ -62,26 +62,26 @@
     return AVIF_TRUE;
 }
 
-avifBool avifStreamReadUX8(avifStream * stream, uint64_t * v, uint64_t factor)
+avifBool avifROStreamReadUX8(avifROStream * stream, uint64_t * v, uint64_t factor)
 {
     if (factor == 0) {
         // Don't read anything, just set to 0
         *v = 0;
     } else if (factor == 1) {
         uint8_t tmp;
-        CHECK(avifStreamRead(stream, &tmp, 1));
+        CHECK(avifROStreamRead(stream, &tmp, 1));
         *v = tmp;
     } else if (factor == 2) {
         uint16_t tmp;
-        CHECK(avifStreamReadU16(stream, &tmp));
+        CHECK(avifROStreamReadU16(stream, &tmp));
         *v = tmp;
     } else if (factor == 4) {
         uint32_t tmp;
-        CHECK(avifStreamReadU32(stream, &tmp));
+        CHECK(avifROStreamReadU32(stream, &tmp));
         *v = tmp;
     } else if (factor == 8) {
         uint64_t tmp;
-        CHECK(avifStreamReadU64(stream, &tmp));
+        CHECK(avifROStreamReadU64(stream, &tmp));
         *v = tmp;
     } else {
         // Unsupported factor
@@ -90,32 +90,32 @@
     return AVIF_TRUE;
 }
 
-avifBool avifStreamReadU16(avifStream * stream, uint16_t * v)
+avifBool avifROStreamReadU16(avifROStream * stream, uint16_t * v)
 {
-    CHECK(avifStreamRead(stream, (uint8_t *)v, sizeof(uint16_t)));
+    CHECK(avifROStreamRead(stream, (uint8_t *)v, sizeof(uint16_t)));
     *v = avifNTOHS(*v);
     return AVIF_TRUE;
 }
 
-avifBool avifStreamReadU32(avifStream * stream, uint32_t * v)
+avifBool avifROStreamReadU32(avifROStream * stream, uint32_t * v)
 {
-    CHECK(avifStreamRead(stream, (uint8_t *)v, sizeof(uint32_t)));
+    CHECK(avifROStreamRead(stream, (uint8_t *)v, sizeof(uint32_t)));
     *v = avifNTOHL(*v);
     return AVIF_TRUE;
 }
 
-avifBool avifStreamReadU64(avifStream * stream, uint64_t * v)
+avifBool avifROStreamReadU64(avifROStream * stream, uint64_t * v)
 {
-    CHECK(avifStreamRead(stream, (uint8_t *)v, sizeof(uint64_t)));
+    CHECK(avifROStreamRead(stream, (uint8_t *)v, sizeof(uint64_t)));
     *v = avifNTOH64(*v);
     return AVIF_TRUE;
 }
 
-avifBool avifStreamReadString(avifStream * stream, char * output, size_t outputSize)
+avifBool avifROStreamReadString(avifROStream * stream, char * output, size_t outputSize)
 {
     // Check for the presence of a null terminator in the stream.
-    size_t remainingBytes = avifStreamRemainingBytes(stream);
-    uint8_t * p = avifStreamCurrent(stream);
+    size_t remainingBytes = avifROStreamRemainingBytes(stream);
+    const uint8_t * p = avifROStreamCurrent(stream);
     avifBool foundNullTerminator = AVIF_FALSE;
     for (size_t i = 0; i < remainingBytes; ++i) {
         if (p[i] == 0) {
@@ -140,36 +140,36 @@
     return AVIF_TRUE;
 }
 
-avifBool avifStreamReadBoxHeader(avifStream * stream, avifBoxHeader * header)
+avifBool avifROStreamReadBoxHeader(avifROStream * stream, avifBoxHeader * header)
 {
     size_t startOffset = stream->offset;
 
     uint32_t smallSize;
-    CHECK(avifStreamReadU32(stream, &smallSize));
-    CHECK(avifStreamRead(stream, header->type, 4));
+    CHECK(avifROStreamReadU32(stream, &smallSize));
+    CHECK(avifROStreamRead(stream, header->type, 4));
 
     uint64_t size = smallSize;
     if (size == 1) {
-        CHECK(avifStreamReadU64(stream, &size));
+        CHECK(avifROStreamReadU64(stream, &size));
     }
 
     if (!memcmp(header->type, "uuid", 4)) {
-        CHECK(avifStreamSkip(stream, 16));
+        CHECK(avifROStreamSkip(stream, 16));
     }
 
     header->size = (size_t)(size - (stream->offset - startOffset));
 
     // Make the assumption here that this box's contents must fit in the remaining portion of the parent stream
-    if (header->size > avifStreamRemainingBytes(stream)) {
+    if (header->size > avifROStreamRemainingBytes(stream)) {
         return AVIF_FALSE;
     }
     return AVIF_TRUE;
 }
 
-avifBool avifStreamReadVersionAndFlags(avifStream * stream, uint8_t * version, uint8_t * flags)
+avifBool avifROStreamReadVersionAndFlags(avifROStream * stream, uint8_t * version, uint8_t * flags)
 {
     uint8_t versionAndFlags[4];
-    CHECK(avifStreamRead(stream, versionAndFlags, 4));
+    CHECK(avifROStreamRead(stream, versionAndFlags, 4));
     if (version) {
         *version = versionAndFlags[0];
     }
@@ -179,18 +179,18 @@
     return AVIF_TRUE;
 }
 
-avifBool avifStreamReadAndEnforceVersion(avifStream * stream, uint8_t enforcedVersion)
+avifBool avifROStreamReadAndEnforceVersion(avifROStream * stream, uint8_t enforcedVersion)
 {
     uint8_t version;
-    CHECK(avifStreamReadVersionAndFlags(stream, &version, NULL));
+    CHECK(avifROStreamReadVersionAndFlags(stream, &version, NULL));
     return (version == enforcedVersion) ? AVIF_TRUE : AVIF_FALSE;
 }
 
 // ---------------------------------------------------------------------------
-// Write
+// avifRWStream
 
 #define AVIF_STREAM_BUFFER_INCREMENT (1024 * 1024)
-static void makeRoom(avifStream * stream, size_t size)
+static void makeRoom(avifRWStream * stream, size_t size)
 {
     size_t neededSize = stream->offset + size;
     size_t newSize = stream->raw->size;
@@ -198,22 +198,41 @@
         newSize += AVIF_STREAM_BUFFER_INCREMENT;
     }
     if (stream->raw->size != newSize) {
-        avifRawDataRealloc(stream->raw, newSize);
+        avifRWDataRealloc(stream->raw, newSize);
     }
 }
 
-void avifStreamFinishWrite(avifStream * stream)
+void avifRWStreamStart(avifRWStream * stream, avifRWData * raw)
+{
+    stream->raw = raw;
+    stream->offset = 0;
+}
+
+size_t avifRWStreamOffset(avifRWStream * stream)
+{
+    return stream->offset;
+}
+
+void avifRWStreamSetOffset(avifRWStream * stream, size_t offset)
+{
+    stream->offset = offset;
+    if (stream->offset > stream->raw->size) {
+        stream->offset = stream->raw->size;
+    }
+}
+
+void avifRWStreamFinishWrite(avifRWStream * stream)
 {
     if (stream->raw->size != stream->offset) {
         if (stream->offset) {
             stream->raw->size = stream->offset;
         } else {
-            avifRawDataFree(stream->raw);
+            avifRWDataFree(stream->raw);
         }
     }
 }
 
-void avifStreamWrite(avifStream * stream, const uint8_t * data, size_t size)
+void avifRWStreamWrite(avifRWStream * stream, const uint8_t * data, size_t size)
 {
     if (!size) {
         return;
@@ -224,12 +243,12 @@
     stream->offset += size;
 }
 
-void avifStreamWriteChars(avifStream * stream, const char * chars, size_t size)
+void avifRWStreamWriteChars(avifRWStream * stream, const char * chars, size_t size)
 {
-    avifStreamWrite(stream, (const uint8_t *)chars, size);
+    avifRWStreamWrite(stream, (const uint8_t *)chars, size);
 }
 
-avifBoxMarker avifStreamWriteBox(avifStream * stream, const char * type, int version, size_t contentSize)
+avifBoxMarker avifRWStreamWriteBox(avifRWStream * stream, const char * type, int version, size_t contentSize)
 {
     avifBoxMarker marker = stream->offset;
     size_t headerSize = sizeof(uint32_t) + 4 /* size of type */;
@@ -250,13 +269,13 @@
     return marker;
 }
 
-void avifStreamFinishBox(avifStream * stream, avifBoxMarker marker)
+void avifRWStreamFinishBox(avifRWStream * stream, avifBoxMarker marker)
 {
     uint32_t noSize = avifNTOHL((uint32_t)(stream->offset - marker));
     memcpy(stream->raw->data + marker, &noSize, sizeof(uint32_t));
 }
 
-void avifStreamWriteU8(avifStream * stream, uint8_t v)
+void avifRWStreamWriteU8(avifRWStream * stream, uint8_t v)
 {
     size_t size = sizeof(uint8_t);
     makeRoom(stream, size);
@@ -264,7 +283,7 @@
     stream->offset += size;
 }
 
-void avifStreamWriteU16(avifStream * stream, uint16_t v)
+void avifRWStreamWriteU16(avifRWStream * stream, uint16_t v)
 {
     size_t size = sizeof(uint16_t);
     v = avifHTONS(v);
@@ -273,7 +292,7 @@
     stream->offset += size;
 }
 
-void avifStreamWriteU32(avifStream * stream, uint32_t v)
+void avifRWStreamWriteU32(avifRWStream * stream, uint32_t v)
 {
     size_t size = sizeof(uint32_t);
     v = avifHTONL(v);
@@ -282,7 +301,7 @@
     stream->offset += size;
 }
 
-void avifStreamWriteZeros(avifStream * stream, size_t byteCount)
+void avifRWStreamWriteZeros(avifRWStream * stream, size_t byteCount)
 {
     makeRoom(stream, byteCount);
     uint8_t * p = stream->raw->data + stream->offset;
diff --git a/src/write.c b/src/write.c
index 3967907..3fd41f0 100644
--- a/src/write.c
+++ b/src/write.c
@@ -21,7 +21,7 @@
 static const size_t alphaURNSize = sizeof(alphaURN);
 
 static avifBool avifImageIsOpaque(avifImage * image);
-static void writeConfigBox(avifStream * s, avifCodecConfigurationBox * cfg);
+static void writeConfigBox(avifRWStream * s, avifCodecConfigurationBox * cfg);
 
 avifEncoder * avifEncoderCreate(void)
 {
@@ -47,15 +47,15 @@
 #endif
 }
 
-avifResult avifEncoderWrite(avifEncoder * encoder, avifImage * image, avifRawData * output)
+avifResult avifEncoderWrite(avifEncoder * encoder, avifImage * image, avifRWData * output)
 {
     if ((image->depth != 8) && (image->depth != 10) && (image->depth != 12)) {
         return AVIF_RESULT_UNSUPPORTED_DEPTH;
     }
 
     avifResult result = AVIF_RESULT_UNKNOWN_ERROR;
-    avifRawData colorOBU = AVIF_RAW_DATA_EMPTY;
-    avifRawData alphaOBU = AVIF_RAW_DATA_EMPTY;
+    avifRWData colorOBU = AVIF_DATA_EMPTY;
+    avifRWData alphaOBU = AVIF_DATA_EMPTY;
     avifCodec * codec[AVIF_CODEC_PLANES_COUNT];
 
     codec[AVIF_CODEC_PLANES_COLOR] = avifCodecCreateForEncode();
@@ -71,8 +71,8 @@
         codec[AVIF_CODEC_PLANES_ALPHA] = avifCodecCreateForEncode();
     }
 
-    avifStream s;
-    avifStreamStart(&s, output);
+    avifRWStream s;
+    avifRWStreamStart(&s, output);
 
     // -----------------------------------------------------------------------
     // Reformat pixels, if need be
@@ -100,7 +100,7 @@
     // -----------------------------------------------------------------------
     // Encode AV1 OBUs
 
-    // avifRawData * alphaOBUPtr = &alphaOBU;
+    // avifRWData * alphaOBUPtr = &alphaOBU;
     // if (avifImageIsOpaque(image)) {
     //     alphaOBUPtr = NULL;
     // }
@@ -122,41 +122,41 @@
     // -----------------------------------------------------------------------
     // Write ftyp
 
-    avifBoxMarker ftyp = avifStreamWriteBox(&s, "ftyp", -1, 0);
-    avifStreamWriteChars(&s, "avif", 4);                           // unsigned int(32) major_brand;
-    avifStreamWriteU32(&s, 0);                                     // unsigned int(32) minor_version;
-    avifStreamWriteChars(&s, "avif", 4);                           // unsigned int(32) compatible_brands[];
-    avifStreamWriteChars(&s, "mif1", 4);                           // ... compatible_brands[]
-    avifStreamWriteChars(&s, "miaf", 4);                           // ... compatible_brands[]
+    avifBoxMarker ftyp = avifRWStreamWriteBox(&s, "ftyp", -1, 0);
+    avifRWStreamWriteChars(&s, "avif", 4);                         // unsigned int(32) major_brand;
+    avifRWStreamWriteU32(&s, 0);                                   // unsigned int(32) minor_version;
+    avifRWStreamWriteChars(&s, "avif", 4);                         // unsigned int(32) compatible_brands[];
+    avifRWStreamWriteChars(&s, "mif1", 4);                         // ... compatible_brands[]
+    avifRWStreamWriteChars(&s, "miaf", 4);                         // ... compatible_brands[]
     if ((image->depth == 8) || (image->depth == 10)) {             //
         if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {        //
-            avifStreamWriteChars(&s, "MA1B", 4);                   // ... compatible_brands[]
+            avifRWStreamWriteChars(&s, "MA1B", 4);                 // ... compatible_brands[]
         } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV444) { //
-            avifStreamWriteChars(&s, "MA1A", 4);                   // ... compatible_brands[]
+            avifRWStreamWriteChars(&s, "MA1A", 4);                 // ... compatible_brands[]
         }
     }
-    avifStreamFinishBox(&s, ftyp);
+    avifRWStreamFinishBox(&s, ftyp);
 
     // -----------------------------------------------------------------------
     // Start meta
 
-    avifBoxMarker meta = avifStreamWriteBox(&s, "meta", 0, 0);
+    avifBoxMarker meta = avifRWStreamWriteBox(&s, "meta", 0, 0);
 
     // -----------------------------------------------------------------------
     // Write hdlr
 
-    avifBoxMarker hdlr = avifStreamWriteBox(&s, "hdlr", 0, 0);
-    avifStreamWriteU32(&s, 0);              // unsigned int(32) pre_defined = 0;
-    avifStreamWriteChars(&s, "pict", 4);    // unsigned int(32) handler_type;
-    avifStreamWriteZeros(&s, 12);           // const unsigned int(32)[3] reserved = 0;
-    avifStreamWriteChars(&s, "libavif", 8); // string name; (writing null terminator)
-    avifStreamFinishBox(&s, hdlr);
+    avifBoxMarker hdlr = avifRWStreamWriteBox(&s, "hdlr", 0, 0);
+    avifRWStreamWriteU32(&s, 0);              // unsigned int(32) pre_defined = 0;
+    avifRWStreamWriteChars(&s, "pict", 4);    // unsigned int(32) handler_type;
+    avifRWStreamWriteZeros(&s, 12);           // const unsigned int(32)[3] reserved = 0;
+    avifRWStreamWriteChars(&s, "libavif", 8); // string name; (writing null terminator)
+    avifRWStreamFinishBox(&s, hdlr);
 
     // -----------------------------------------------------------------------
     // Write pitm
 
-    avifStreamWriteBox(&s, "pitm", 0, sizeof(uint16_t));
-    avifStreamWriteU16(&s, 1); //  unsigned int(16) item_ID;
+    avifRWStreamWriteBox(&s, "pitm", 0, sizeof(uint16_t));
+    avifRWStreamWriteU16(&s, 1); //  unsigned int(16) item_ID;
 
     // -----------------------------------------------------------------------
     // Write iloc
@@ -165,74 +165,74 @@
     size_t colorOBUOffsetOffset = 0;
     size_t alphaOBUOffsetOffset = 0;
 
-    avifBoxMarker iloc = avifStreamWriteBox(&s, "iloc", 0, 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;
-    avifStreamWrite(&s, &offsetSizeAndLengthSize, 1);      //
-    avifStreamWriteZeros(&s, 1);                           // unsigned int(4) base_offset_size;
+    avifRWStreamWrite(&s, &offsetSizeAndLengthSize, 1);    //
+    avifRWStreamWriteZeros(&s, 1);                         // unsigned int(4) base_offset_size;
                                                            // unsigned int(4) reserved;
-    avifStreamWriteU16(&s, hasAlpha ? 2 : 1);              // unsigned int(16) item_count;
+    avifRWStreamWriteU16(&s, hasAlpha ? 2 : 1);            // unsigned int(16) item_count;
 
     // Item ID #1 (Color OBU)
-    avifStreamWriteU16(&s, 1);                       // unsigned int(16) item_ID;
-    avifStreamWriteU16(&s, 0);                       // unsigned int(16) data_reference_index;
-    avifStreamWriteU16(&s, 1);                       // unsigned int(16) extent_count;
-    colorOBUOffsetOffset = avifStreamOffset(&s);     //
-    avifStreamWriteU32(&s, 0 /* set later */);       // unsigned int(offset_size*8) extent_offset;
-    avifStreamWriteU32(&s, (uint32_t)colorOBU.size); // unsigned int(length_size*8) extent_length;
+    avifRWStreamWriteU16(&s, 1);                       // 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) {
-        avifStreamWriteU16(&s, 2);                       // unsigned int(16) item_ID;
-        avifStreamWriteU16(&s, 0);                       // unsigned int(16) data_reference_index;
-        avifStreamWriteU16(&s, 1);                       // unsigned int(16) extent_count;
-        alphaOBUOffsetOffset = avifStreamOffset(&s);     //
-        avifStreamWriteU32(&s, 0 /* set later */);       // unsigned int(offset_size*8) extent_offset;
-        avifStreamWriteU32(&s, (uint32_t)alphaOBU.size); // unsigned int(length_size*8) extent_length;
+        avifRWStreamWriteU16(&s, 2);                       // 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;
     }
 
-    avifStreamFinishBox(&s, iloc);
+    avifRWStreamFinishBox(&s, iloc);
 
     // -----------------------------------------------------------------------
     // Write iinf
 
-    avifBoxMarker iinf = avifStreamWriteBox(&s, "iinf", 0, 0);
-    avifStreamWriteU16(&s, hasAlpha ? 2 : 1); //  unsigned int(16) entry_count;
+    avifBoxMarker iinf = avifRWStreamWriteBox(&s, "iinf", 0, 0);
+    avifRWStreamWriteU16(&s, hasAlpha ? 2 : 1); //  unsigned int(16) entry_count;
 
-    avifBoxMarker infe0 = avifStreamWriteBox(&s, "infe", 2, 0);
-    avifStreamWriteU16(&s, 1);            // unsigned int(16) item_ID;
-    avifStreamWriteU16(&s, 0);            // unsigned int(16) item_protection_index;
-    avifStreamWriteChars(&s, "av01", 4);  // unsigned int(32) item_type;
-    avifStreamWriteChars(&s, "Color", 6); // string item_name; (writing null terminator)
-    avifStreamFinishBox(&s, infe0);
+    avifBoxMarker infe0 = avifRWStreamWriteBox(&s, "infe", 2, 0);
+    avifRWStreamWriteU16(&s, 1);            // 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, infe0);
     if (hasAlpha) {
-        avifBoxMarker infe1 = avifStreamWriteBox(&s, "infe", 2, 0);
-        avifStreamWriteU16(&s, 2);            // unsigned int(16) item_ID;
-        avifStreamWriteU16(&s, 0);            // unsigned int(16) item_protection_index;
-        avifStreamWriteChars(&s, "av01", 4);  // unsigned int(32) item_type;
-        avifStreamWriteChars(&s, "Alpha", 6); // string item_name; (writing null terminator)
-        avifStreamFinishBox(&s, infe1);
+        avifBoxMarker infe1 = avifRWStreamWriteBox(&s, "infe", 2, 0);
+        avifRWStreamWriteU16(&s, 2);            // 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, infe1);
     }
-    avifStreamFinishBox(&s, iinf);
+    avifRWStreamFinishBox(&s, iinf);
 
     // -----------------------------------------------------------------------
     // Write iref (auxl) for alpha, if any
 
     if (hasAlpha) {
-        avifBoxMarker iref = avifStreamWriteBox(&s, "iref", 0, 0);
-        avifBoxMarker auxl = avifStreamWriteBox(&s, "auxl", -1, 0);
-        avifStreamWriteU16(&s, 2); // unsigned int(16) from_item_ID;
-        avifStreamWriteU16(&s, 1); // unsigned int(16) reference_count;
-        avifStreamWriteU16(&s, 1); // unsigned int(16) to_item_ID;
-        avifStreamFinishBox(&s, auxl);
-        avifStreamFinishBox(&s, iref);
+        avifBoxMarker iref = avifRWStreamWriteBox(&s, "iref", 0, 0);
+        avifBoxMarker auxl = avifRWStreamWriteBox(&s, "auxl", -1, 0);
+        avifRWStreamWriteU16(&s, 2); // unsigned int(16) from_item_ID;
+        avifRWStreamWriteU16(&s, 1); // unsigned int(16) reference_count;
+        avifRWStreamWriteU16(&s, 1); // unsigned int(16) to_item_ID;
+        avifRWStreamFinishBox(&s, auxl);
+        avifRWStreamFinishBox(&s, iref);
     }
 
     // -----------------------------------------------------------------------
     // Write iprp->ipco->ispe
 
-    avifBoxMarker iprp = avifStreamWriteBox(&s, "iprp", -1, 0);
+    avifBoxMarker iprp = avifRWStreamWriteBox(&s, "iprp", -1, 0);
     {
         uint8_t ipcoIndex = 0;
         struct ipmaArray ipmaColor;
@@ -240,42 +240,42 @@
         struct ipmaArray ipmaAlpha;
         memset(&ipmaAlpha, 0, sizeof(ipmaAlpha));
 
-        avifBoxMarker ipco = avifStreamWriteBox(&s, "ipco", -1, 0);
+        avifBoxMarker ipco = avifRWStreamWriteBox(&s, "ipco", -1, 0);
         {
-            avifBoxMarker ispe = avifStreamWriteBox(&s, "ispe", 0, 0);
-            avifStreamWriteU32(&s, image->width);  // unsigned int(32) image_width;
-            avifStreamWriteU32(&s, image->height); // unsigned int(32) image_height;
-            avifStreamFinishBox(&s, ispe);
+            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
 
             if (image->profileFormat == AVIF_PROFILE_FORMAT_NCLX) {
-                avifBoxMarker colr = avifStreamWriteBox(&s, "colr", -1, 0);
-                avifStreamWriteChars(&s, "nclx", 4);                         // unsigned int(32) colour_type;
-                avifStreamWriteU16(&s, image->nclx.colourPrimaries);         // unsigned int(16) colour_primaries;
-                avifStreamWriteU16(&s, image->nclx.transferCharacteristics); // unsigned int(16) transfer_characteristics;
-                avifStreamWriteU16(&s, image->nclx.matrixCoefficients);      // unsigned int(16) matrix_coefficients;
-                avifStreamWriteU8(&s, image->nclx.fullRangeFlag & 0x80);     // unsigned int(1) full_range_flag;
-                                                                             // unsigned int(7) reserved = 0;
-                avifStreamFinishBox(&s, colr);
+                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;
+                avifRWStreamFinishBox(&s, colr);
                 ++ipcoIndex;
                 ipmaPush(&ipmaColor, ipcoIndex);
             } else if ((image->profileFormat == AVIF_PROFILE_FORMAT_ICC) && image->icc.data && (image->icc.size > 0)) {
-                avifBoxMarker colr = avifStreamWriteBox(&s, "colr", -1, 0);
-                avifStreamWriteChars(&s, "prof", 4); // unsigned int(32) colour_type;
-                avifStreamWrite(&s, image->icc.data, image->icc.size);
-                avifStreamFinishBox(&s, colr);
+                avifBoxMarker colr = avifRWStreamWriteBox(&s, "colr", -1, 0);
+                avifRWStreamWriteChars(&s, "prof", 4); // unsigned int(32) colour_type;
+                avifRWStreamWrite(&s, image->icc.data, image->icc.size);
+                avifRWStreamFinishBox(&s, colr);
                 ++ipcoIndex;
                 ipmaPush(&ipmaColor, ipcoIndex);
             }
 
-            avifBoxMarker pixiC = avifStreamWriteBox(&s, "pixi", 0, 0);
-            avifStreamWriteU8(&s, 3);                     // unsigned int (8) num_channels;
-            avifStreamWriteU8(&s, (uint8_t)image->depth); // unsigned int (8) bits_per_channel;
-            avifStreamWriteU8(&s, (uint8_t)image->depth); // unsigned int (8) bits_per_channel;
-            avifStreamWriteU8(&s, (uint8_t)image->depth); // unsigned int (8) bits_per_channel;
-            avifStreamFinishBox(&s, pixiC);
+            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);
 
@@ -286,10 +286,10 @@
             ipmaPush(&ipmaColor, ipcoIndex);
 
             if (hasAlpha) {
-                avifBoxMarker pixiA = avifStreamWriteBox(&s, "pixi", 0, 0);
-                avifStreamWriteU8(&s, 1);                     // unsigned int (8) num_channels;
-                avifStreamWriteU8(&s, (uint8_t)image->depth); // unsigned int (8) bits_per_channel;
-                avifStreamFinishBox(&s, pixiA);
+                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);
 
@@ -299,70 +299,70 @@
                 ++ipcoIndex;
                 ipmaPush(&ipmaAlpha, ipcoIndex);
 
-                avifBoxMarker auxC = avifStreamWriteBox(&s, "auxC", 0, 0);
-                avifStreamWriteChars(&s, alphaURN, alphaURNSize); //  string aux_type;
-                avifStreamFinishBox(&s, auxC);
+                avifBoxMarker auxC = avifRWStreamWriteBox(&s, "auxC", 0, 0);
+                avifRWStreamWriteChars(&s, alphaURN, alphaURNSize); //  string aux_type;
+                avifRWStreamFinishBox(&s, auxC);
                 ++ipcoIndex;
                 ipmaPush(&ipmaAlpha, ipcoIndex);
             }
         }
-        avifStreamFinishBox(&s, ipco);
+        avifRWStreamFinishBox(&s, ipco);
 
-        avifBoxMarker ipma = avifStreamWriteBox(&s, "ipma", 0, 0);
+        avifBoxMarker ipma = avifRWStreamWriteBox(&s, "ipma", 0, 0);
         {
             int ipmaCount = hasAlpha ? 2 : 1;
-            avifStreamWriteU32(&s, ipmaCount); // unsigned int(32) entry_count;
+            avifRWStreamWriteU32(&s, ipmaCount); // unsigned int(32) entry_count;
 
-            avifStreamWriteU16(&s, 1);                            // unsigned int(16) item_ID;
-            avifStreamWriteU8(&s, ipmaColor.count);               // unsigned int(8) association_count;
-            for (int i = 0; i < ipmaColor.count; ++i) {           //
-                avifStreamWriteU8(&s, ipmaColor.associations[i]); // bit(1) essential; unsigned int(7) property_index;
+            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) {
-                avifStreamWriteU16(&s, 2);                            // unsigned int(16) item_ID;
-                avifStreamWriteU8(&s, ipmaAlpha.count);               // unsigned int(8) association_count;
-                for (int i = 0; i < ipmaAlpha.count; ++i) {           //
-                    avifStreamWriteU8(&s, ipmaAlpha.associations[i]); // bit(1) essential; unsigned int(7) property_index;
+                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;
                 }
             }
         }
-        avifStreamFinishBox(&s, ipma);
+        avifRWStreamFinishBox(&s, ipma);
     }
-    avifStreamFinishBox(&s, iprp);
+    avifRWStreamFinishBox(&s, iprp);
 
     // -----------------------------------------------------------------------
     // Finish meta box
 
-    avifStreamFinishBox(&s, meta);
+    avifRWStreamFinishBox(&s, meta);
 
     // -----------------------------------------------------------------------
     // Write mdat
 
-    avifBoxMarker mdat = avifStreamWriteBox(&s, "mdat", -1, 0);
+    avifBoxMarker mdat = avifRWStreamWriteBox(&s, "mdat", -1, 0);
     uint32_t colorOBUOffset = (uint32_t)s.offset;
-    avifStreamWrite(&s, colorOBU.data, colorOBU.size);
+    avifRWStreamWrite(&s, colorOBU.data, colorOBU.size);
     uint32_t alphaOBUOffset = (uint32_t)s.offset;
-    avifStreamWrite(&s, alphaOBU.data, alphaOBU.size);
-    avifStreamFinishBox(&s, mdat);
+    avifRWStreamWrite(&s, alphaOBU.data, alphaOBU.size);
+    avifRWStreamFinishBox(&s, mdat);
 
     // -----------------------------------------------------------------------
     // Finish up stream
 
     // Set offsets needed in meta box based on where we eventually wrote mdat
-    size_t prevOffset = avifStreamOffset(&s);
+    size_t prevOffset = avifRWStreamOffset(&s);
     if (colorOBUOffsetOffset != 0) {
-        avifStreamSetOffset(&s, colorOBUOffsetOffset);
-        avifStreamWriteU32(&s, colorOBUOffset);
+        avifRWStreamSetOffset(&s, colorOBUOffsetOffset);
+        avifRWStreamWriteU32(&s, colorOBUOffset);
     }
     if (alphaOBUOffsetOffset != 0) {
-        avifStreamSetOffset(&s, alphaOBUOffsetOffset);
-        avifStreamWriteU32(&s, alphaOBUOffset);
+        avifRWStreamSetOffset(&s, alphaOBUOffsetOffset);
+        avifRWStreamWriteU32(&s, alphaOBUOffset);
     }
-    avifStreamSetOffset(&s, prevOffset);
+    avifRWStreamSetOffset(&s, prevOffset);
 
     // Close write stream
-    avifStreamFinishWrite(&s);
+    avifRWStreamFinishWrite(&s);
 
     // -----------------------------------------------------------------------
     // IO stats
@@ -382,8 +382,8 @@
     if (codec[AVIF_CODEC_PLANES_ALPHA]) {
         avifCodecDestroy(codec[AVIF_CODEC_PLANES_ALPHA]);
     }
-    avifRawDataFree(&colorOBU);
-    avifRawDataFree(&alphaOBU);
+    avifRWDataFree(&colorOBU);
+    avifRWDataFree(&alphaOBU);
     return result;
 }
 
@@ -415,17 +415,17 @@
     return AVIF_TRUE;
 }
 
-static void writeConfigBox(avifStream * s, avifCodecConfigurationBox * cfg)
+static void writeConfigBox(avifRWStream * s, avifCodecConfigurationBox * cfg)
 {
-    avifBoxMarker av1C = avifStreamWriteBox(s, "av1C", -1, 0);
+    avifBoxMarker av1C = avifRWStreamWriteBox(s, "av1C", -1, 0);
 
     // unsigned int (1) marker = 1;
     // unsigned int (7) version = 1;
-    avifStreamWriteU8(s, 0x80 | 0x1);
+    avifRWStreamWriteU8(s, 0x80 | 0x1);
 
     // unsigned int (3) seq_profile;
     // unsigned int (5) seq_level_idx_0;
-    avifStreamWriteU8(s, (uint8_t)((cfg->seqProfile & 0x7) << 5) | (uint8_t)(cfg->seqLevelIdx0 & 0x1f));
+    avifRWStreamWriteU8(s, (uint8_t)((cfg->seqProfile & 0x7) << 5) | (uint8_t)(cfg->seqLevelIdx0 & 0x1f));
 
     uint8_t bits = 0;
     bits |= (cfg->seqTier0 & 0x1) << 7;           // unsigned int (1) seq_tier_0;
@@ -435,7 +435,7 @@
     bits |= (cfg->chromaSubsamplingX & 0x1) << 3; // unsigned int (1) chroma_subsampling_x;
     bits |= (cfg->chromaSubsamplingY & 0x1) << 2; // unsigned int (1) chroma_subsampling_y;
     bits |= (cfg->chromaSamplePosition & 0x3);    // unsigned int (2) chroma_sample_position;
-    avifStreamWriteU8(s, bits);
+    avifRWStreamWriteU8(s, bits);
 
     // unsigned int (3) reserved = 0;
     // unsigned int (1) initial_presentation_delay_present;
@@ -444,7 +444,7 @@
     // } else {
     //   unsigned int (4) reserved = 0;
     // }
-    avifStreamWriteU8(s, 0);
+    avifRWStreamWriteU8(s, 0);
 
-    avifStreamFinishBox(s, av1C);
+    avifRWStreamFinishBox(s, av1C);
 }