Use libyuv for 12-bit YUV->RGB when available

Generalize avifImageYUVToRGBLibYUV10bpc() to
avifImageYUVToRGBLibYUVHighBitDepth() and use it for both 10bpc and
12bpc. The 12bpc part currently uses I012ToARGBMatrix() only.

I012ToARGBMatrix() was added in
https://chromium-review.googlesource.com/c/libyuv/libyuv/+/2727775. That
commit is between version 1780 and version 1781. See
https://chromium-review.googlesource.com/c/libyuv/libyuv/+/2707003 and
https://chromium-review.googlesource.com/c/libyuv/libyuv/+/2746780.
diff --git a/src/reformat_libyuv.c b/src/reformat_libyuv.c
index 88a67f9..3a37ba0 100644
--- a/src/reformat_libyuv.c
+++ b/src/reformat_libyuv.c
@@ -236,10 +236,10 @@
                                               avifRGBImage * rgb,
                                               const struct YuvConstants * matrixYUV,
                                               const struct YuvConstants * matrixYVU);
-static avifResult avifImageYUVToRGBLibYUV10bpc(const avifImage * image,
-                                               avifRGBImage * rgb,
-                                               const struct YuvConstants * matrixYUV,
-                                               const struct YuvConstants * matrixYVU);
+static avifResult avifImageYUVToRGBLibYUVHighBitDepth(const avifImage * image,
+                                                      avifRGBImage * rgb,
+                                                      const struct YuvConstants * matrixYUV,
+                                                      const struct YuvConstants * matrixYVU);
 
 avifResult avifImageYUVToRGBLibYUV(const avifImage * image, avifRGBImage * rgb)
 {
@@ -387,8 +387,8 @@
         return avifImageYUVToRGBLibYUV8bpc(image, rgb, matrixYUV, matrixYVU);
     }
 
-    if ((image->depth == 10) && (rgb->depth == 8)) {
-        return avifImageYUVToRGBLibYUV10bpc(image, rgb, matrixYUV, matrixYVU);
+    if (((image->depth == 10) || (image->depth == 12)) && (rgb->depth == 8)) {
+        return avifImageYUVToRGBLibYUVHighBitDepth(image, rgb, matrixYUV, matrixYVU);
     }
 
     // This function didn't do anything; use the built-in YUV conversion
@@ -412,6 +412,9 @@
 #if LIBYUV_VERSION < 1756
 #define I400ToARGBMatrix NULL
 #endif
+#if LIBYUV_VERSION < 1781
+#define I012ToARGBMatrix NULL
+#endif
 
 // Lookup table for isYVU. If the entry in this table is AVIF_TRUE, then it
 // means that we are using a libyuv function with R and B channels swapped,
@@ -558,14 +561,15 @@
     return AVIF_RESULT_NOT_IMPLEMENTED;
 }
 
-avifResult avifImageYUVToRGBLibYUV10bpc(const avifImage * image,
-                                        avifRGBImage * rgb,
-                                        const struct YuvConstants * matrixYUV,
-                                        const struct YuvConstants * matrixYVU)
+avifResult avifImageYUVToRGBLibYUVHighBitDepth(const avifImage * image,
+                                               avifRGBImage * rgb,
+                                               const struct YuvConstants * matrixYUV,
+                                               const struct YuvConstants * matrixYVU)
 {
     // See if the current settings can be accomplished with libyuv, and use it (if possible).
 
-    assert((image->depth == 10) && (rgb->depth == 8));
+    assert(((image->depth == 10) || (image->depth == 12)) && (rgb->depth == 8));
+    int depthIndex = (image->depth == 10) ? 0 : 1;
 
     // libavif uses byte-order when describing pixel formats, such that the R in RGBA is the lowest address,
     // similar to PNG. libyuv orders in word-order, so libavif's RGBA would be referred to in libyuv as ABGR.
@@ -600,16 +604,28 @@
                                         int,
                                         int,
                                         enum FilterMode);
-    YUVToRGBMatrixFilter lutYuvToRgbMatrixFilter[AVIF_RGB_FORMAT_COUNT][AVIF_PIXEL_FORMAT_COUNT] = {
-        { NULL, NULL, NULL, NULL, NULL },                                     // RGB
-        { NULL, NULL, I210ToARGBMatrixFilter, I010ToARGBMatrixFilter, NULL }, // RGBA
-        { NULL, NULL, NULL, NULL, NULL },                                     // ARGB
-        { NULL, NULL, NULL, NULL, NULL },                                     // BGR
-        { NULL, NULL, I210ToARGBMatrixFilter, I010ToARGBMatrixFilter, NULL }, // BGRA
-        { NULL, NULL, NULL, NULL, NULL },                                     // ABGR
-        { NULL, NULL, NULL, NULL, NULL },                                     // RGB_565
+    // First index: 0: 10bpc, 1: 12bpc
+    YUVToRGBMatrixFilter lutYuvToRgbMatrixFilter[2][AVIF_RGB_FORMAT_COUNT][AVIF_PIXEL_FORMAT_COUNT] = {
+        {
+            { NULL, NULL, NULL, NULL, NULL },                                     // RGB
+            { NULL, NULL, I210ToARGBMatrixFilter, I010ToARGBMatrixFilter, NULL }, // RGBA
+            { NULL, NULL, NULL, NULL, NULL },                                     // ARGB
+            { NULL, NULL, NULL, NULL, NULL },                                     // BGR
+            { NULL, NULL, I210ToARGBMatrixFilter, I010ToARGBMatrixFilter, NULL }, // BGRA
+            { NULL, NULL, NULL, NULL, NULL },                                     // ABGR
+            { NULL, NULL, NULL, NULL, NULL },                                     // RGB_565
+        },
+        {
+            { NULL, NULL, NULL, NULL, NULL }, // RGB
+            { NULL, NULL, NULL, NULL, NULL }, // RGBA
+            { NULL, NULL, NULL, NULL, NULL }, // ARGB
+            { NULL, NULL, NULL, NULL, NULL }, // BGR
+            { NULL, NULL, NULL, NULL, NULL }, // BGRA
+            { NULL, NULL, NULL, NULL, NULL }, // ABGR
+            { NULL, NULL, NULL, NULL, NULL }, // RGB_565
+        },
     };
-    YUVToRGBMatrixFilter yuvToRgbMatrixFilter = lutYuvToRgbMatrixFilter[rgb->format][image->yuvFormat];
+    YUVToRGBMatrixFilter yuvToRgbMatrixFilter = lutYuvToRgbMatrixFilter[depthIndex][rgb->format][image->yuvFormat];
     if (yuvToRgbMatrixFilter != NULL) {
         // 'None' (Nearest neighbor) filter is faster than bilinear.
         enum FilterMode filter = (rgb->chromaUpsampling == AVIF_CHROMA_UPSAMPLING_FASTEST) ? kFilterNone : kFilterBilinear;
@@ -633,16 +649,28 @@
     // Lookup table for YUV To RGB Matrix (without filter).
     typedef int (
         *YUVToRGBMatrix)(const uint16_t *, int, const uint16_t *, int, const uint16_t *, int, uint8_t *, int, const struct YuvConstants *, int, int);
-    YUVToRGBMatrix lutYuvToRgbMatrix[AVIF_RGB_FORMAT_COUNT][AVIF_PIXEL_FORMAT_COUNT] = {
-        { NULL, NULL, NULL, NULL, NULL },                                     // RGB
-        { NULL, I410ToARGBMatrix, I210ToARGBMatrix, I010ToARGBMatrix, NULL }, // RGBA
-        { NULL, NULL, NULL, NULL, NULL },                                     // ARGB
-        { NULL, NULL, NULL, NULL, NULL },                                     // BGR
-        { NULL, I410ToARGBMatrix, I210ToARGBMatrix, I010ToARGBMatrix, NULL }, // BGRA
-        { NULL, NULL, NULL, NULL, NULL },                                     // ABGR
-        { NULL, NULL, NULL, NULL, NULL },                                     // RGB_565
+    // First index: 0: 10bpc, 1: 12bpc
+    YUVToRGBMatrix lutYuvToRgbMatrix[2][AVIF_RGB_FORMAT_COUNT][AVIF_PIXEL_FORMAT_COUNT] = {
+        {
+            { NULL, NULL, NULL, NULL, NULL },                                     // RGB
+            { NULL, I410ToARGBMatrix, I210ToARGBMatrix, I010ToARGBMatrix, NULL }, // RGBA
+            { NULL, NULL, NULL, NULL, NULL },                                     // ARGB
+            { NULL, NULL, NULL, NULL, NULL },                                     // BGR
+            { NULL, I410ToARGBMatrix, I210ToARGBMatrix, I010ToARGBMatrix, NULL }, // BGRA
+            { NULL, NULL, NULL, NULL, NULL },                                     // ABGR
+            { NULL, NULL, NULL, NULL, NULL },                                     // RGB_565
+        },
+        {
+            { NULL, NULL, NULL, NULL, NULL },             // RGB
+            { NULL, NULL, NULL, I012ToARGBMatrix, NULL }, // RGBA
+            { NULL, NULL, NULL, NULL, NULL },             // ARGB
+            { NULL, NULL, NULL, NULL, NULL },             // BGR
+            { NULL, NULL, NULL, I012ToARGBMatrix, NULL }, // BGRA
+            { NULL, NULL, NULL, NULL, NULL },             // ABGR
+            { NULL, NULL, NULL, NULL, NULL },             // RGB_565
+        },
     };
-    YUVToRGBMatrix yuvToRgbMatrix = lutYuvToRgbMatrix[rgb->format][image->yuvFormat];
+    YUVToRGBMatrix yuvToRgbMatrix = lutYuvToRgbMatrix[depthIndex][rgb->format][image->yuvFormat];
     if (yuvToRgbMatrix != NULL) {
         if (yuvToRgbMatrix((const uint16_t *)image->yuvPlanes[AVIF_CHAN_Y],
                            image->yuvRowBytes[AVIF_CHAN_Y] / 2,