Skip to content

Commit 0f430db

Browse files
authored
Fix avifDecSampleTransformItemValidateProperties()
Return BMFF_PARSE_FAILED intead of INTERNAL_ERROR on missing ispe. Implement TODO about verifying av1C consistency. Fix comment wrongly referring to item being a grid instead of a sato.
1 parent cc3e5dd commit 0f430db

1 file changed

Lines changed: 89 additions & 19 deletions

File tree

src/read.c

Lines changed: 89 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ static avifCodecType avifGetCodecType(const uint8_t * fourcc)
5656

5757
static const char * avifGetConfigurationPropertyName(avifCodecType codecType)
5858
{
59+
static const char kUnknown[] = "****";
5960
switch (codecType) {
6061
case AVIF_CODEC_TYPE_AV1:
6162
return "av1C";
@@ -65,7 +66,7 @@ static const char * avifGetConfigurationPropertyName(avifCodecType codecType)
6566
#endif
6667
default:
6768
assert(AVIF_FALSE);
68-
return NULL;
69+
return kUnknown; // Easier to deal with than NULL.
6970
}
7071
}
7172

@@ -2297,11 +2298,30 @@ static avifResult avifParseSampleTransformImageBox(const uint8_t * raw,
22972298
return AVIF_RESULT_OK;
22982299
}
22992300

2300-
static avifResult avifDecoderSampleTransformItemValidateProperties(const avifDecoderItem * item, avifDiagnostics * diag)
2301+
static const avifProperty * avifDecoderItemCodecConfigOrFirstCellCodecConfig(const avifDecoderItem * item)
23012302
{
2302-
const avifProperty * pixiProp = avifPropertyArrayFind(&item->properties, "pixi");
2303+
if (!memcmp(item->type, "grid", 4)) {
2304+
// In case of a grid, return the codec configuration property of the first cell.
2305+
// avifDecoderAdoptGridTileCodecType() copies that property from the first cell to the grid item anyway.
2306+
for (uint32_t i = 0; i < item->meta->items.count; ++i) {
2307+
avifDecoderItem * inputImageItem = item->meta->items.item[i];
2308+
if (inputImageItem->dimgForID == item->id) {
2309+
return avifPropertyArrayFind(&inputImageItem->properties,
2310+
avifGetConfigurationPropertyName(avifGetCodecType(inputImageItem->type)));
2311+
}
2312+
}
2313+
// The number of tiles was verified in avifDecoderItemReadAndParse().
2314+
assert(AVIF_FALSE);
2315+
}
2316+
return avifPropertyArrayFind(&item->properties, avifGetConfigurationPropertyName(avifGetCodecType(item->type)));
2317+
}
2318+
2319+
static avifResult avifDecoderSampleTransformItemValidateProperties(const avifDecoderItem * satoItem, avifDiagnostics * diag)
2320+
{
2321+
AVIF_ASSERT_OR_RETURN(memcmp(satoItem->type, "sato", 4) == 0);
2322+
const avifProperty * pixiProp = avifPropertyArrayFind(&satoItem->properties, "pixi");
23032323
if (!pixiProp) {
2304-
avifDiagnosticsPrintf(diag, "Item ID %u of type '%.4s' is missing mandatory pixi property", item->id, (const char *)item->type);
2324+
avifDiagnosticsPrintf(diag, "Item ID %u of type 'sato' is missing mandatory pixi property", satoItem->id);
23052325
return AVIF_RESULT_BMFF_PARSE_FAILED;
23062326
}
23072327
for (uint8_t i = 1; i < pixiProp->u.pixi.planeCount; ++i) {
@@ -2311,32 +2331,59 @@ static avifResult avifDecoderSampleTransformItemValidateProperties(const avifDec
23112331
AVIF_ASSERT_OR_RETURN(pixiProp->u.pixi.planeCount >= 1);
23122332
const uint8_t depth = pixiProp->u.pixi.planeDepths[0];
23132333
if (depth != 8 && depth != 10 && depth != 12 && depth != 16) {
2314-
avifDiagnosticsPrintf(diag, "Item ID %u depth specified by pixi property [%u] is not supported", item->id, depth);
2334+
avifDiagnosticsPrintf(diag,
2335+
"Item ID %u of type 'sato' with depth %u (specified by pixi property) is not supported",
2336+
satoItem->id,
2337+
depth);
23152338
return AVIF_RESULT_NOT_IMPLEMENTED;
23162339
}
23172340

2318-
const avifProperty * ispeProp = avifPropertyArrayFind(&item->properties, "ispe");
2341+
const avifProperty * ispeProp = avifPropertyArrayFind(&satoItem->properties, "ispe");
23192342
if (!ispeProp) {
2320-
avifDiagnosticsPrintf(diag, "Item ID %u of type '%.4s' is missing mandatory ispe property", item->id, (const char *)item->type);
2343+
avifDiagnosticsPrintf(diag, "Item ID %u of type 'sato' is missing mandatory ispe property", satoItem->id);
23212344
return AVIF_RESULT_BMFF_PARSE_FAILED;
23222345
}
23232346

2324-
// If item is a grid, check that its input image items share the same properties.
2325-
for (uint32_t i = 0; i < item->meta->items.count; ++i) {
2326-
avifDecoderItem * inputImageItem = item->meta->items.item[i];
2327-
if (inputImageItem->dimgForID != item->id) {
2347+
// Check that all input image items of the 'sato' derived image item share the same properties.
2348+
for (uint32_t i = 0; i < satoItem->meta->items.count; ++i) {
2349+
avifDecoderItem * inputImageItem = satoItem->meta->items.item[i];
2350+
if (inputImageItem->dimgForID != satoItem->id) {
23282351
continue;
23292352
}
2353+
2354+
// Require all input image items of the 'sato' derived image item to be associated with a ImageSpatialExtentsProperty.
23302355
const avifProperty * inputImageItemIspeProp = avifPropertyArrayFind(&inputImageItem->properties, "ispe");
2331-
AVIF_ASSERT_OR_RETURN(inputImageItemIspeProp != NULL);
2356+
if (inputImageItemIspeProp == NULL) {
2357+
avifDiagnosticsPrintf(diag, "Item ID %u is missing mandatory ispe property", inputImageItem->id);
2358+
return AVIF_RESULT_BMFF_PARSE_FAILED;
2359+
}
2360+
2361+
// The codec configuration property must be present, at least on the first cell for a 'grid' item.
2362+
const avifProperty * inputImageItemCodecConfig = avifDecoderItemCodecConfigOrFirstCellCodecConfig(inputImageItem);
2363+
if (inputImageItemCodecConfig == NULL) {
2364+
avifDiagnosticsPrintf(diag,
2365+
"Item ID %u of type '%.4s' is missing mandatory codec configuration property",
2366+
inputImageItem->id,
2367+
(const char *)inputImageItem->type);
2368+
return AVIF_RESULT_BMFF_PARSE_FAILED;
2369+
}
23322370

2333-
for (uint32_t j = i + 1; j < item->meta->items.count; ++j) {
2334-
avifDecoderItem * otherInputImageItem = item->meta->items.item[j];
2335-
if (otherInputImageItem->dimgForID != item->id) {
2371+
for (uint32_t j = i + 1; j < satoItem->meta->items.count; ++j) {
2372+
avifDecoderItem * otherInputImageItem = satoItem->meta->items.item[j];
2373+
if (otherInputImageItem->dimgForID != satoItem->id) {
23362374
continue;
23372375
}
2376+
2377+
// Require all input image items of the 'sato' derived image item to be associated with a ImageSpatialExtentsProperty.
23382378
const avifProperty * otherInputImageItemIspeProp = avifPropertyArrayFind(&otherInputImageItem->properties, "ispe");
2339-
AVIF_ASSERT_OR_RETURN(otherInputImageItemIspeProp != NULL);
2379+
if (otherInputImageItemIspeProp == NULL) {
2380+
avifDiagnosticsPrintf(diag,
2381+
"Item ID %u of type '%.4s' is missing mandatory ispe property",
2382+
otherInputImageItem->id,
2383+
(const char *)otherInputImageItem->type);
2384+
return AVIF_RESULT_BMFF_PARSE_FAILED;
2385+
}
2386+
23402387
if (inputImageItemIspeProp->u.ispe.width != otherInputImageItemIspeProp->u.ispe.width ||
23412388
inputImageItemIspeProp->u.ispe.height != otherInputImageItemIspeProp->u.ispe.height) {
23422389
avifDiagnosticsPrintf(diag,
@@ -2347,12 +2394,35 @@ static avifResult avifDecoderSampleTransformItemValidateProperties(const avifDec
23472394
return AVIF_RESULT_BMFF_PARSE_FAILED;
23482395
}
23492396

2350-
// TODO(yguyon): Check that all input image items share the same codec config (except for the bit depth value).
2397+
// The codec configuration property must be present, at least on the first cell for a 'grid' item.
2398+
const avifProperty * otherInputImageItemCodecConfig = avifDecoderItemCodecConfigOrFirstCellCodecConfig(otherInputImageItem);
2399+
if (otherInputImageItemCodecConfig == NULL) {
2400+
avifDiagnosticsPrintf(diag,
2401+
"Item ID %u of type '%.4s' is missing mandatory codec configuration property",
2402+
otherInputImageItem->id,
2403+
(const char *)otherInputImageItem->type);
2404+
return AVIF_RESULT_BMFF_PARSE_FAILED;
2405+
}
2406+
2407+
if (inputImageItemCodecConfig->u.av1C.monochrome != otherInputImageItemCodecConfig->u.av1C.monochrome ||
2408+
inputImageItemCodecConfig->u.av1C.chromaSubsamplingX != otherInputImageItemCodecConfig->u.av1C.chromaSubsamplingX ||
2409+
inputImageItemCodecConfig->u.av1C.chromaSubsamplingY != otherInputImageItemCodecConfig->u.av1C.chromaSubsamplingY ||
2410+
inputImageItemCodecConfig->u.av1C.chromaSamplePosition != otherInputImageItemCodecConfig->u.av1C.chromaSamplePosition) {
2411+
avifDiagnosticsPrintf(diag,
2412+
"The plane count or subsampling in the codec configuration property of item ID %u of type '%.4s' differs from item ID %u",
2413+
inputImageItem->id,
2414+
(const char *)inputImageItem->type,
2415+
otherInputImageItem->id);
2416+
return AVIF_RESULT_BMFF_PARSE_FAILED;
2417+
}
2418+
2419+
// If the input image item of the 'sato' derived image item is itself a grid,
2420+
// its own input image items will be checked in avifDecoderItemValidateProperties().
23512421
}
23522422
break;
23532423
}
23542424

2355-
AVIF_CHECKERR(avifPropertyArrayFind(&item->properties, "clap") == NULL, AVIF_RESULT_NOT_IMPLEMENTED);
2425+
AVIF_CHECKERR(avifPropertyArrayFind(&satoItem->properties, "clap") == NULL, AVIF_RESULT_NOT_IMPLEMENTED);
23562426
return AVIF_RESULT_OK;
23572427
}
23582428

@@ -6419,7 +6489,7 @@ avifResult avifDecoderReset(avifDecoder * decoder)
64196489
AVIF_ASSERT_OR_RETURN(decoder->image->gainMap && decoder->image->gainMap->image);
64206490
decoder->image->gainMap->image->width = mainItems[AVIF_ITEM_GAIN_MAP]->width;
64216491
decoder->image->gainMap->image->height = mainItems[AVIF_ITEM_GAIN_MAP]->height;
6422-
// Must be called after avifDecoderGenerateImageTiles() which among other things copies the
6492+
// Must be called after avifDecoderAdoptGridTileCodecType() which among other things copies the
64236493
// codec config property from the first tile of a grid to the grid item (when grids are used).
64246494
AVIF_CHECKRES(avifReadCodecConfigProperty(decoder->image->gainMap->image,
64256495
&mainItems[AVIF_ITEM_GAIN_MAP]->properties,

0 commit comments

Comments
 (0)