Reland "heif: Add AVIF type and AVIF sniffing"

This is a reland of 3ab5b73649554934a2ef23f3682c2a1e5487e1c3

Fix: Chromium does not use the heif decoder. So hide it behind
an ifdef.

Original change's description:
> heif: Add AVIF type and AVIF sniffing
>
> AVIF is the image format based on the AV1 video codec. The
> container for AVIF is very similar to that of HEIF. Add type
> definitions for AVIF and sniffing code for detecting AVIF images.
>
> The underlying android platform's HEIF decoder implementation will
> also support AVIF decoding.
>
> Bug: b/141654151
> Change-Id: I7e31f4cedf0bffb8920ddf880a26601e48d0e833
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/330059
> Reviewed-by: Leon Scroggins <scroggo@google.com>
> Reviewed-by: Derek Sollenberger <djsollen@google.com>
> Reviewed-by: Chong Zhang <chz@google.com>
> Commit-Queue: Leon Scroggins <scroggo@google.com>

Bug: b/141654151
Change-Id: Ie6840d6fc97789be619924fc60df8683cd58430f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/331496
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
diff --git a/src/codec/SkHeifCodec.cpp b/src/codec/SkHeifCodec.cpp
index 3627a7b..2813c0e 100644
--- a/src/codec/SkHeifCodec.cpp
+++ b/src/codec/SkHeifCodec.cpp
@@ -18,11 +18,11 @@
 #define FOURCC(c1, c2, c3, c4) \
     ((c1) << 24 | (c2) << 16 | (c3) << 8 | (c4))
 
-bool SkHeifCodec::IsHeif(const void* buffer, size_t bytesRead) {
-    // Parse the ftyp box up to bytesRead to determine if this is HEIF.
+std::optional<SkEncodedImageFormat> SkHeifCodec::IsSupported(const void* buffer, size_t bytesRead) {
+    // Parse the ftyp box up to bytesRead to determine if this is HEIF or AVIF.
     // Any valid ftyp box should have at least 8 bytes.
     if (bytesRead < 8) {
-        return false;
+        return std::nullopt;
     }
 
     uint32_t* ptr = (uint32_t*)buffer;
@@ -30,7 +30,7 @@
     uint32_t chunkType = SkEndian_SwapBE32(ptr[1]);
 
     if (chunkType != FOURCC('f', 't', 'y', 'p')) {
-        return false;
+        return std::nullopt;
     }
 
     int64_t offset = 8;
@@ -38,18 +38,18 @@
         // This indicates that the next 8 bytes represent the chunk size,
         // and chunk data comes after that.
         if (bytesRead < 16) {
-            return false;
+            return std::nullopt;
         }
         auto* chunkSizePtr = SkTAddOffset<const uint64_t>(buffer, offset);
         chunkSize = SkEndian_SwapBE64(*chunkSizePtr);
         if (chunkSize < 16) {
             // The smallest valid chunk is 16 bytes long in this case.
-            return false;
+            return std::nullopt;
         }
         offset += 8;
     } else if (chunkSize < 8) {
         // The smallest valid chunk is 8 bytes long.
-        return false;
+        return std::nullopt;
     }
 
     if (chunkSize > bytesRead) {
@@ -59,10 +59,11 @@
     // It should at least have major brand (4-byte) and minor version (4-bytes).
     // The rest of the chunk (if any) is a list of (4-byte) compatible brands.
     if (chunkDataSize < 8) {
-        return false;
+        return std::nullopt;
     }
 
     uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
+    bool isHeif = false;
     for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
         if (i == 1) {
             // Skip this index, it refers to the minorVersion,
@@ -72,11 +73,23 @@
         auto* brandPtr = SkTAddOffset<const uint32_t>(buffer, offset + 4 * i);
         uint32_t brand = SkEndian_SwapBE32(*brandPtr);
         if (brand == FOURCC('m', 'i', 'f', '1') || brand == FOURCC('h', 'e', 'i', 'c')
-         || brand == FOURCC('m', 's', 'f', '1') || brand == FOURCC('h', 'e', 'v', 'c')) {
-            return true;
+         || brand == FOURCC('m', 's', 'f', '1') || brand == FOURCC('h', 'e', 'v', 'c')
+         || brand == FOURCC('a', 'v', 'i', 'f') || brand == FOURCC('a', 'v', 'i', 's')) {
+            // AVIF files could have "mif1" as the major brand. So we cannot
+            // distinguish whether the image is AVIF or HEIC just based on the
+            // "mif1" brand. So wait until we see a specific avif brand to
+            // determine whether it is AVIF or HEIC.
+            isHeif = true;
+            if (brand == FOURCC('a', 'v', 'i', 'f')
+              || brand == FOURCC('a', 'v', 'i', 's')) {
+                return SkEncodedImageFormat::kAVIF;
+            }
         }
     }
-    return false;
+    if (isHeif) {
+      return SkEncodedImageFormat::kHEIF;
+    }
+    return std::nullopt;
 }
 
 static SkEncodedOrigin get_orientation(const HeifFrameInfo& frameInfo) {
@@ -123,7 +136,7 @@
 }
 
 std::unique_ptr<SkCodec> SkHeifCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
-        SkCodec::SelectionPolicy selectionPolicy, Result* result) {
+        SkCodec::SelectionPolicy selectionPolicy, SkEncodedImageFormat format, Result* result) {
     std::unique_ptr<HeifDecoder> heifDecoder(createHeifDecoder());
     if (heifDecoder == nullptr) {
         *result = kInternalError;
@@ -162,19 +175,21 @@
 
     *result = kSuccess;
     return std::unique_ptr<SkCodec>(new SkHeifCodec(
-            std::move(info), heifDecoder.release(), orientation, frameCount > 1));
+            std::move(info), heifDecoder.release(), orientation, frameCount > 1, format));
 }
 
 SkHeifCodec::SkHeifCodec(
         SkEncodedInfo&& info,
         HeifDecoder* heifDecoder,
         SkEncodedOrigin origin,
-        bool useAnimation)
+        bool useAnimation,
+        SkEncodedImageFormat format)
     : INHERITED(std::move(info), skcms_PixelFormat_RGBA_8888, nullptr, origin)
     , fHeifDecoder(heifDecoder)
     , fSwizzleSrcRow(nullptr)
     , fColorXformSrcRow(nullptr)
     , fUseAnimation(useAnimation)
+    , fFormat(format)
 {}
 
 bool SkHeifCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaque,