Skip to content

Commit

Permalink
Split and document avifParseCodecConfiguration()
Browse files Browse the repository at this point in the history
Mirror the changes of read.c to write.c too.
  • Loading branch information
y-guyon committed Aug 11, 2023
1 parent 9d81bcd commit 127bd7e
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 20 deletions.
55 changes: 39 additions & 16 deletions src/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -1862,24 +1862,16 @@ static avifBool avifParseContentLightLevelInformationBox(avifProperty * prop, co
return AVIF_TRUE;
}

static avifBool avifParseCodecConfigurationBoxProperty(avifProperty * prop,
const uint8_t * raw,
size_t rawLen,
const char * configPropName,
avifDiagnostics * diag)
// Implementation of section 2.3.3. of AV1 Codec ISO Media File Format Binding specification v1.2.0.
// See https://aomediacodec.github.io/av1-isobmff/v1.2.0.html#av1codecconfigurationbox-syntax.
static avifBool avifParseCodecConfiguration(avifROStream * s, avifCodecConfigurationBox * config, const char * configPropName, avifDiagnostics * diag)
{
char diagContext[] = "Box[....]";
snprintf(diagContext, sizeof(diagContext), "Box[%.4s]", configPropName); // "Box[av1C]" or "Box[av2C]"
BEGIN_STREAM(s, raw, rawLen, diag, diagContext);

avifCodecConfigurationBox * config = &prop->u.av1C;

uint8_t markerAndVersion = 0;
AVIF_CHECK(avifROStreamRead(&s, &markerAndVersion, 1));
AVIF_CHECK(avifROStreamRead(s, &markerAndVersion, 1));
uint8_t seqProfileAndIndex = 0;
AVIF_CHECK(avifROStreamRead(&s, &seqProfileAndIndex, 1));
AVIF_CHECK(avifROStreamRead(s, &seqProfileAndIndex, 1));
uint8_t rawFlags = 0;
AVIF_CHECK(avifROStreamRead(&s, &rawFlags, 1));
AVIF_CHECK(avifROStreamRead(s, &rawFlags, 1));

if (markerAndVersion != 0x81) {
// Marker and version must both == 1
Expand All @@ -1896,9 +1888,41 @@ static avifBool avifParseCodecConfigurationBoxProperty(avifProperty * prop,
config->chromaSubsamplingX = (rawFlags >> 3) & 0x1; // unsigned int (1) chroma_subsampling_x;
config->chromaSubsamplingY = (rawFlags >> 2) & 0x1; // unsigned int (1) chroma_subsampling_y;
config->chromaSamplePosition = (rawFlags >> 0) & 0x3; // unsigned int (2) chroma_sample_position;

// unsigned int (3) reserved = 0;
// unsigned int (1) initial_presentation_delay_present;
// if (initial_presentation_delay_present) {
// unsigned int (4) initial_presentation_delay_minus_one;
// } else {
// unsigned int (4) reserved = 0;
// }
AVIF_CHECK(avifROStreamSkip(s, 1));

// According to section 2.2.1. of AV1 Image File Format specification v1.1.0:
// "- Sequence Header OBUs should not be present in the AV1CodecConfigurationBox."
// "- If a Sequence Header OBU is present in the AV1CodecConfigurationBox,
// it shall match the Sequence Header OBU in the AV1 Image Item Data."
// "- Metadata OBUs, if present, shall match the values given in other item properties,
// such as the PixelInformationProperty or ColourInformationBox."
// See https://aomediacodec.github.io/av1-avif/v1.1.0.html#av1-configuration-item-property.
// For simplicity, the constraints above are not enforced.
// The following is skipped by avifParseItemPropertyContainerBox().
// unsigned int (8) configOBUs[];
return AVIF_TRUE;
}

static avifBool avifParseCodecConfigurationBoxProperty(avifProperty * prop,
const uint8_t * raw,
size_t rawLen,
const char * configPropName,
avifDiagnostics * diag)
{
char diagContext[] = "Box[....]";
snprintf(diagContext, sizeof(diagContext), "Box[%.4s]", configPropName); // "Box[av1C]" or "Box[av2C]"
BEGIN_STREAM(s, raw, rawLen, diag, diagContext);
return avifParseCodecConfiguration(&s, &prop->u.av1C, configPropName, diag);
}

static avifBool avifParsePixelAspectRatioBoxProperty(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
{
BEGIN_STREAM(s, raw, rawLen, diag, "Box[pasp]");
Expand Down Expand Up @@ -2386,7 +2410,7 @@ static avifBool avifParseItemInfoEntry(avifMeta * meta, const uint8_t * raw, siz

avifDecoderItem * item = avifMetaFindItem(meta, itemID);
if (!item) {
avifDiagnosticsPrintf(diag, "Box[infe] has an invalid item ID [%u]", itemID);
avifDiagnosticsPrintf(diag, "%s: Box[infe] of type %.4s has an invalid item ID [%u]", s.diagContext, itemType, itemID);
return AVIF_FALSE;
}

Expand Down Expand Up @@ -4120,7 +4144,6 @@ avifResult avifDecoderReset(avifDecoder * decoder)
decoder->image->yuvFormat = AVIF_PIXEL_FORMAT_YUV420;
} else if (configProp->u.av1C.chromaSubsamplingX) {
decoder->image->yuvFormat = AVIF_PIXEL_FORMAT_YUV422;

} else {
decoder->image->yuvFormat = AVIF_PIXEL_FORMAT_YUV444;
}
Expand Down
34 changes: 30 additions & 4 deletions src/write.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ static const size_t alphaURNSize = sizeof(alphaURN);
static const char xmpContentType[] = AVIF_CONTENT_TYPE_XMP;
static const size_t xmpContentTypeSize = sizeof(xmpContentType);

static void writeConfigBox(avifRWStream * s, avifCodecConfigurationBox * cfg, const char * configPropName);
static void writeConfigBox(avifRWStream * s, const avifCodecConfigurationBox * cfg, const char * configPropName);

// ---------------------------------------------------------------------------
// avifSetTileConfiguration
Expand Down Expand Up @@ -417,6 +417,7 @@ avifEncoder * avifEncoderCreate(void)
return NULL;
}
memset(encoder, 0, sizeof(avifEncoder));
encoder->codecChoice = AVIF_CODEC_CHOICE_AUTO;
encoder->maxThreads = 1;
encoder->speed = AVIF_SPEED_DEFAULT;
encoder->keyframeInterval = 0;
Expand Down Expand Up @@ -536,6 +537,12 @@ static avifBool avifEncoderDetectChanges(const avifEncoder * encoder, avifEncode
return AVIF_TRUE;
}

// Subset of avifEncoderWriteColorProperties() for the properties clli, pasp, clap, irot, imir.
static void avifEncoderWriteExtendedColorProperties(avifRWStream * outputStream,
const avifImage * imageMetadata,
struct ipmaArray * ipma,
avifItemPropertyDedup * dedup);

// This function is used in two codepaths:
// * writing color *item* properties
// * writing color *track* properties
Expand Down Expand Up @@ -590,6 +597,15 @@ static void avifEncoderWriteColorProperties(avifRWStream * outputStream,
ipmaPush(ipma, avifItemPropertyDedupFinish(dedup, outputStream), AVIF_FALSE);
}

avifEncoderWriteExtendedColorProperties(outputStream, imageMetadata, ipma, dedup);
}

static void avifEncoderWriteExtendedColorProperties(avifRWStream * outputStream,
const avifImage * imageMetadata,
struct ipmaArray * ipma,
avifItemPropertyDedup * dedup)
{
avifRWStream * s = dedup ? &dedup->s : outputStream;
// Write Content Light Level Information, if present
if (imageMetadata->clli.maxCLL || imageMetadata->clli.maxPALL) {
if (dedup) {
Expand Down Expand Up @@ -2174,10 +2190,10 @@ avifResult avifEncoderWrite(avifEncoder * encoder, const avifImage * image, avif
return avifEncoderFinish(encoder, output);
}

static void writeConfigBox(avifRWStream * s, avifCodecConfigurationBox * cfg, const char * configPropName)
// Implementation of section 2.3.3. of AV1 Codec ISO Media File Format Binding specification v1.2.0.
// See https://aomediacodec.github.io/av1-isobmff/v1.2.0.html#av1codecconfigurationbox-syntax.
static void writeCodecConfig(avifRWStream * s, const avifCodecConfigurationBox * cfg)
{
avifBoxMarker configBox = avifRWStreamWriteBox(s, configPropName, AVIF_BOX_SIZE_TBD);

// unsigned int (1) marker = 1;
// unsigned int (7) version = 1;
avifRWStreamWriteU8(s, 0x80 | 0x1);
Expand Down Expand Up @@ -2205,5 +2221,15 @@ static void writeConfigBox(avifRWStream * s, avifCodecConfigurationBox * cfg, co
// }
avifRWStreamWriteU8(s, 0);

// According to section 2.2.1. of AV1 Image File Format specification v1.1.0,
// there is no need to write any OBU here.
// See https://aomediacodec.github.io/av1-avif/v1.1.0.html#av1-configuration-item-property.
// unsigned int (8) configOBUs[];
}

static void writeConfigBox(avifRWStream * s, const avifCodecConfigurationBox * cfg, const char * configPropName)
{
avifBoxMarker configBox = avifRWStreamWriteBox(s, configPropName, AVIF_BOX_SIZE_TBD);
writeCodecConfig(s, cfg);
avifRWStreamFinishBox(s, configBox);
}

0 comments on commit 127bd7e

Please sign in to comment.