Expose animation track presence in avifDecoder
Add a member `animationTrackPresent` to `avifDecoder` which will
be set to true if an animation track is found in the input image.
Fixes #1595
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c52ebbb..bb71b61 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -38,6 +38,7 @@
Add --scaling-mode flag to set scaling mode of each layer.
This part of AV1 encoder is not as thoroughly tested, so there are higher
possibility encoder may crash when given certain configuration or input.
+* Add imageSequenceTrackPresent flag to the avifDecoder struct.
### Changed
* Update aom.cmd: v3.7.0
diff --git a/include/avif/avif.h b/include/avif/avif.h
index f926149..53a41a0 100644
--- a/include/avif/avif.h
+++ b/include/avif/avif.h
@@ -1160,6 +1160,11 @@
// Can be useful to decode the gain map image only.
avifBool ignoreColorAndAlpha;
#endif
+
+ // This is true when avifDecoderParse() detects an image sequence track in the image. If this is true, the image can be
+ // decoded either as an animated image sequence or as a still image (the primary image item) by setting avifDecoderSetSource
+ // to the appropriate source.
+ avifBool imageSequenceTrackPresent;
} avifDecoder;
AVIF_API avifDecoder * avifDecoderCreate(void);
diff --git a/src/read.c b/src/read.c
index 50a52e8..57e8a75 100644
--- a/src/read.c
+++ b/src/read.c
@@ -3664,6 +3664,7 @@
AVIF_CHECKERR(avifParseMovieBox(data, boxOffset, boxContents.data, boxContents.size, decoder->imageSizeLimit, decoder->imageDimensionLimit),
AVIF_RESULT_BMFF_PARSE_FAILED);
moovSeen = AVIF_TRUE;
+ decoder->imageSequenceTrackPresent = AVIF_TRUE;
#if defined(AVIF_ENABLE_EXPERIMENTAL_AVIR)
} else if (!memcmp(header.type, "coni", 4)) {
AVIF_CHECKERR(!metaSeen && !moovSeen, AVIF_RESULT_BMFF_PARSE_FAILED);
diff --git a/tests/gtest/avifanimationtest.cc b/tests/gtest/avifanimationtest.cc
index 4b89058..b7e2a3f 100644
--- a/tests/gtest/avifanimationtest.cc
+++ b/tests/gtest/avifanimationtest.cc
@@ -23,6 +23,7 @@
AVIF_RESULT_OK);
ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK);
EXPECT_EQ(decoder->alphaPresent, AVIF_FALSE);
+ EXPECT_EQ(decoder->imageSequenceTrackPresent, AVIF_TRUE);
EXPECT_EQ(decoder->imageCount, 5);
EXPECT_EQ(decoder->repetitionCount, 0);
for (int i = 0; i < 5; ++i) {
@@ -30,6 +31,33 @@
}
}
+TEST(AvifDecodeTest, AnimatedImageWithSourceSetToPrimaryItem) {
+ if (!testutil::Av1DecoderAvailable()) {
+ GTEST_SKIP() << "AV1 Codec unavailable, skip test.";
+ }
+ const char* file_name = "colors-animated-8bpc.avif";
+ testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
+ ASSERT_NE(decoder, nullptr);
+ ASSERT_EQ(avifDecoderSetIOFile(decoder.get(),
+ (std::string(data_path) + file_name).c_str()),
+ AVIF_RESULT_OK);
+ ASSERT_EQ(
+ avifDecoderSetSource(decoder.get(), AVIF_DECODER_SOURCE_PRIMARY_ITEM),
+ AVIF_RESULT_OK);
+ ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK);
+ EXPECT_EQ(decoder->alphaPresent, AVIF_FALSE);
+ EXPECT_EQ(decoder->imageSequenceTrackPresent, AVIF_TRUE);
+ // imageCount is expected to be 1 because we are using primary item as the
+ // preferred source.
+ EXPECT_EQ(decoder->imageCount, 1);
+ EXPECT_EQ(decoder->repetitionCount, 0);
+ // Get the first (and only) image.
+ EXPECT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
+ // Subsequent calls should not return AVIF_RESULT_OK since there is only one
+ // image in the preferred source.
+ EXPECT_NE(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
+}
+
} // namespace
} // namespace libavif
diff --git a/tests/gtest/avifbasictest.cc b/tests/gtest/avifbasictest.cc
index 657d4f6..2d3f0c2 100644
--- a/tests/gtest/avifbasictest.cc
+++ b/tests/gtest/avifbasictest.cc
@@ -28,6 +28,7 @@
result = avifDecoderReadMemory(decoder.get(), decoded.get(), encoded.data,
encoded.size);
ASSERT_EQ(result, AVIF_RESULT_OK) << avifResultToString(result);
+ EXPECT_EQ(decoder->imageSequenceTrackPresent, AVIF_FALSE);
// Verify that the input and decoded images are close.
ASSERT_GT(testutil::GetPsnr(*image, *decoded), 40.0);
diff --git a/tests/gtest/avifdecodetest.cc b/tests/gtest/avifdecodetest.cc
index 7342b3c..2d8b937 100644
--- a/tests/gtest/avifdecodetest.cc
+++ b/tests/gtest/avifdecodetest.cc
@@ -24,6 +24,7 @@
AVIF_RESULT_OK);
ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK);
EXPECT_EQ(decoder->alphaPresent, AVIF_TRUE);
+ EXPECT_EQ(decoder->imageSequenceTrackPresent, AVIF_FALSE);
EXPECT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
EXPECT_NE(decoder->image->alphaPlane, nullptr);
EXPECT_GT(decoder->image->alphaRowBytes, 0u);