Eliminate the libYUVUsage enum, and simply document when libyuv fast paths will / will not be exercised
diff --git a/apps/avifdec.c b/apps/avifdec.c
index efe31e0..4f1c362 100644
--- a/apps/avifdec.c
+++ b/apps/avifdec.c
@@ -94,7 +94,6 @@
avifBool infoOnly = AVIF_FALSE;
avifChromaUpsampling chromaUpsampling = AVIF_CHROMA_UPSAMPLING_AUTOMATIC;
avifBool ignoreICC = AVIF_FALSE;
- avifLibYUVUsage libYUVUsage = AVIF_LIBYUV_USAGE_DISABLED; // Use built-in paths by default for consistency and control over subsampling
if (argc < 2) {
syntax();
@@ -152,8 +151,6 @@
infoOnly = AVIF_TRUE;
} else if (!strcmp(arg, "--ignore-icc")) {
ignoreICC = AVIF_TRUE;
- } else if (!strcmp(arg, "--libyuv")) {
- libYUVUsage = AVIF_LIBYUV_USAGE_AUTOMATIC;
} else {
// Positional argument
if (!inputFilename) {
@@ -214,11 +211,11 @@
returnCode = 1;
}
} else if (outputFormat == AVIF_APP_FILE_FORMAT_JPEG) {
- if (!avifJPEGWrite(avif, outputFilename, jpegQuality, chromaUpsampling, libYUVUsage)) {
+ if (!avifJPEGWrite(avif, outputFilename, jpegQuality, chromaUpsampling)) {
returnCode = 1;
}
} else if (outputFormat == AVIF_APP_FILE_FORMAT_PNG) {
- if (!avifPNGWrite(avif, outputFilename, requestedDepth, chromaUpsampling, libYUVUsage)) {
+ if (!avifPNGWrite(avif, outputFilename, requestedDepth, chromaUpsampling)) {
returnCode = 1;
}
} else {
diff --git a/apps/shared/avifjpeg.c b/apps/shared/avifjpeg.c
index 3f13da1..e3719a8 100644
--- a/apps/shared/avifjpeg.c
+++ b/apps/shared/avifjpeg.c
@@ -111,7 +111,7 @@
return ret;
}
-avifBool avifJPEGWrite(avifImage * avif, const char * outputFilename, int jpegQuality, avifChromaUpsampling chromaUpsampling, avifLibYUVUsage libYUVUsage)
+avifBool avifJPEGWrite(avifImage * avif, const char * outputFilename, int jpegQuality, avifChromaUpsampling chromaUpsampling)
{
avifBool ret = AVIF_FALSE;
FILE * f = NULL;
@@ -126,7 +126,6 @@
avifRGBImageSetDefaults(&rgb, avif);
rgb.format = AVIF_RGB_FORMAT_RGB;
rgb.chromaUpsampling = chromaUpsampling;
- rgb.libYUVUsage = libYUVUsage;
rgb.depth = 8;
avifRGBImageAllocatePixels(&rgb);
if (avifImageYUVToRGB(avif, &rgb) != AVIF_RESULT_OK) {
diff --git a/apps/shared/avifjpeg.h b/apps/shared/avifjpeg.h
index 8b41e82..4eefa90 100644
--- a/apps/shared/avifjpeg.h
+++ b/apps/shared/avifjpeg.h
@@ -7,6 +7,6 @@
#include "avif/avif.h"
avifBool avifJPEGRead(avifImage * avif, const char * inputFilename, avifPixelFormat requestedFormat, uint32_t requestedDepth);
-avifBool avifJPEGWrite(avifImage * avif, const char * outputFilename, int jpegQuality, avifChromaUpsampling chromaUpsampling, avifLibYUVUsage libYUVUsage);
+avifBool avifJPEGWrite(avifImage * avif, const char * outputFilename, int jpegQuality, avifChromaUpsampling chromaUpsampling);
#endif // ifndef LIBAVIF_APPS_SHARED_AVIFJPEG_H
diff --git a/apps/shared/avifpng.c b/apps/shared/avifpng.c
index ae7ecbd..9cb1113 100644
--- a/apps/shared/avifpng.c
+++ b/apps/shared/avifpng.c
@@ -155,7 +155,7 @@
return readResult;
}
-avifBool avifPNGWrite(avifImage * avif, const char * outputFilename, uint32_t requestedDepth, avifChromaUpsampling chromaUpsampling, avifLibYUVUsage libYUVUsage)
+avifBool avifPNGWrite(avifImage * avif, const char * outputFilename, uint32_t requestedDepth, avifChromaUpsampling chromaUpsampling)
{
volatile avifBool writeResult = AVIF_FALSE;
png_structp png = NULL;
@@ -178,7 +178,6 @@
avifRGBImageSetDefaults(&rgb, avif);
rgb.depth = rgbDepth;
rgb.chromaUpsampling = chromaUpsampling;
- rgb.libYUVUsage = libYUVUsage;
avifRGBImageAllocatePixels(&rgb);
if (avifImageYUVToRGB(avif, &rgb) != AVIF_RESULT_OK) {
fprintf(stderr, "Conversion to RGB failed: %s\n", outputFilename);
diff --git a/apps/shared/avifpng.h b/apps/shared/avifpng.h
index 246d6c2..38f87e0 100644
--- a/apps/shared/avifpng.h
+++ b/apps/shared/avifpng.h
@@ -8,10 +8,6 @@
// if (requestedDepth == 0), do best-fit
avifBool avifPNGRead(avifImage * avif, const char * inputFilename, avifPixelFormat requestedFormat, uint32_t requestedDepth, uint32_t * outPNGDepth);
-avifBool avifPNGWrite(avifImage * avif,
- const char * outputFilename,
- uint32_t requestedDepth,
- avifChromaUpsampling chromaUpsampling,
- avifLibYUVUsage libYUVUsage);
+avifBool avifPNGWrite(avifImage * avif, const char * outputFilename, uint32_t requestedDepth, avifChromaUpsampling chromaUpsampling);
#endif // ifndef LIBAVIF_APPS_SHARED_AVIFPNG_H
diff --git a/include/avif/avif.h b/include/avif/avif.h
index 35ca8e2..a2aca7a 100644
--- a/include/avif/avif.h
+++ b/include/avif/avif.h
@@ -379,6 +379,19 @@
// conversion, if necessary. Pixels in an avifRGBImage buffer are always full range, and conversion
// routines will fail if the width and height don't match the associated avifImage.
+// If libavif is built with libyuv fast paths enabled, libavif will use libyuv for conversion from
+// YUV to RGB if the following requirements are met:
+//
+// * YUV depth: 8
+// * RGB depth: 8
+// * rgb.chromaUpsampling: AVIF_CHROMA_UPSAMPLING_AUTOMATIC (and upsampling is required: 420/422)
+// * rgb.format: AVIF_RGB_FORMAT_RGBA, AVIF_RGB_FORMAT_BGRA (420/422 support for AVIF_RGB_FORMAT_ABGR, AVIF_RGB_FORMAT_ARGB)
+// * CICP is one of the following combinations (CP/TC/MC/Range):
+// * x/x/[2|5|6]/Full
+// * [5|6]/x/12/Full
+// * x/x/[1|2|5|6|9]/Limited
+// * [1|2|5|6|9]/x/12/Limited
+
typedef enum avifRGBFormat
{
AVIF_RGB_FORMAT_RGB = 0,
@@ -393,18 +406,11 @@
typedef enum avifChromaUpsampling
{
- AVIF_CHROMA_UPSAMPLING_AUTOMATIC = 0, // Chooses the best quality upsampling given the settings (currently bilinear always)
+ AVIF_CHROMA_UPSAMPLING_AUTOMATIC = 0, // Chooses the best quality upsampling (given the settings)
AVIF_CHROMA_UPSAMPLING_NEAREST = 1, // Faster and uglier
AVIF_CHROMA_UPSAMPLING_BILINEAR = 2 // Slower and prettier
} avifChromaUpsampling;
-typedef enum avifLibYUVUsage
-{
- AVIF_LIBYUV_USAGE_AUTOMATIC = 0, // Use libyuv if compiled-in and possible with the current settings (default)
- AVIF_LIBYUV_USAGE_DISABLED, // Avoid libyuv conversion, even if it is available
- AVIF_LIBYUV_USAGE_REQUIRED // If libyuv is unavailable or if the current combination cannot use it, fail
-} avifLibYUVUsage;
-
typedef struct avifRGBImage
{
uint32_t width; // must match associated avifImage
@@ -416,9 +422,6 @@
avifBool ignoreAlpha; // Used for XRGB formats, treats formats containing alpha (such as ARGB) as if they were
// RGB, treating the alpha bits as if they were all 1.
- avifLibYUVUsage libYUVUsage; // Defaults to "automatic", but can be forced on or off for easy testing,
- // or avoiding unexpected (slower) YUV paths.
-
uint8_t * pixels;
uint32_t rowBytes;
} avifRGBImage;
diff --git a/src/avif.c b/src/avif.c
index 08ae313..f8efe91 100644
--- a/src/avif.c
+++ b/src/avif.c
@@ -356,7 +356,6 @@
rgb->format = AVIF_RGB_FORMAT_RGBA;
rgb->chromaUpsampling = AVIF_CHROMA_UPSAMPLING_AUTOMATIC;
rgb->ignoreAlpha = AVIF_FALSE;
- rgb->libYUVUsage = AVIF_LIBYUV_USAGE_AUTOMATIC;
rgb->pixels = NULL;
rgb->rowBytes = 0;
}
diff --git a/src/reformat.c b/src/reformat.c
index 2eba3a5..795ad9f 100644
--- a/src/reformat.c
+++ b/src/reformat.c
@@ -957,18 +957,12 @@
}
avifBool convertedWithLibYUV = AVIF_FALSE;
- if (rgb->libYUVUsage != AVIF_LIBYUV_USAGE_DISABLED) {
- avifResult libyuvResult = avifImageYUVToRGBLibYUV(image, rgb);
- if (libyuvResult == AVIF_RESULT_OK) {
- convertedWithLibYUV = AVIF_TRUE;
- } else {
- if (libyuvResult != AVIF_RESULT_NO_CONTENT) {
- return libyuvResult;
- }
- if (rgb->libYUVUsage == AVIF_LIBYUV_USAGE_REQUIRED) {
- // libyuv was required, and the current combination couldn't be done with libyuv
- return AVIF_RESULT_REFORMAT_FAILED;
- }
+ avifResult libyuvResult = avifImageYUVToRGBLibYUV(image, rgb);
+ if (libyuvResult == AVIF_RESULT_OK) {
+ convertedWithLibYUV = AVIF_TRUE;
+ } else {
+ if (libyuvResult != AVIF_RESULT_NO_CONTENT) {
+ return libyuvResult;
}
}
diff --git a/src/reformat_libyuv.c b/src/reformat_libyuv.c
index e8b94a1..6fa5291 100644
--- a/src/reformat_libyuv.c
+++ b/src/reformat_libyuv.c
@@ -36,6 +36,13 @@
return AVIF_RESULT_NO_CONTENT;
}
+ if ((image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) || (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422)) {
+ if (rgb->chromaUpsampling != AVIF_CHROMA_UPSAMPLING_AUTOMATIC) {
+ // libyuv uses its own upsampling filter. If the enduser chose a specific one, avoid using libyuv.
+ return AVIF_RESULT_NO_CONTENT;
+ }
+ }
+
// Find the correct libyuv YuvConstants, based on range and CP/MC
const struct YuvConstants * matrixYUV = NULL;
const struct YuvConstants * matrixYVU = NULL;
@@ -51,11 +58,11 @@
switch (image->colorPrimaries) {
case AVIF_COLOR_PRIMARIES_BT470BG:
case AVIF_COLOR_PRIMARIES_BT601:
- case AVIF_COLOR_PRIMARIES_UNSPECIFIED:
matrixYUV = &kYuvJPEGConstants;
matrixYVU = &kYvuJPEGConstants;
break;
+ case AVIF_COLOR_PRIMARIES_UNSPECIFIED:
case AVIF_COLOR_PRIMARIES_UNKNOWN:
case AVIF_COLOR_PRIMARIES_BT709:
case AVIF_COLOR_PRIMARIES_BT470M:
@@ -101,12 +108,12 @@
case AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL:
switch (image->colorPrimaries) {
case AVIF_COLOR_PRIMARIES_BT709:
+ case AVIF_COLOR_PRIMARIES_UNSPECIFIED:
matrixYUV = &kYuvH709Constants;
matrixYVU = &kYvuH709Constants;
break;
case AVIF_COLOR_PRIMARIES_BT470BG:
case AVIF_COLOR_PRIMARIES_BT601:
- case AVIF_COLOR_PRIMARIES_UNSPECIFIED:
matrixYUV = &kYuvI601Constants;
matrixYVU = &kYvuI601Constants;
break;