Created new cmake option AVIF_CODEC_AOM, reorganized struct avifCodec to prepare for other codec impls
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 273f3fc..2be50e2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,13 +6,10 @@
 
 ## [Unreleased]
 ### Added
-- Added install rules in CMake
+- Added new CMake option `AVIF_CODEC_AOM` to enable/disable the usage of AOM's codec (default: on)
 
 ### Changed
-- Minor CMake cleanup
-
-### Changed
-- Various README url updates to point at official repo
+- Reorganized internal struct avifCodec to accomodate multiple codecs simultaneously (compile time; not exposed to API)
 
 ## [0.2.0] - 2019-06-12
 ### Added
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4bc35a9..70c337a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,14 +8,11 @@
   add_definitions(-std=c99) # Enforce C99 for gcc
 endif()
 
+option(AVIF_CODEC_AOM "Use the AOM codec for encoding (and decoding if no other decoder is present)" ON)
+
 add_subdirectory(ext)
 
-include_directories(
-    include
-    "${CMAKE_CURRENT_SOURCE_DIR}/ext/aom"
-    "${AOM_BINARY_DIR}"
-)
-
+include_directories(include)
 if(NOT AVIF_EXTERNAL_GB)
     include_directories("${CMAKE_CURRENT_SOURCE_DIR}/ext/gb")
 endif()
@@ -34,13 +31,21 @@
     src/write.c
 )
 
-# TODO: Support other codec implementations here
-set(AVIF_SRCS ${AVIF_SRCS}
-    src/codec_aom.c
-)
+set(AVIF_CODEC_LIBARIES)
+if(AVIF_CODEC_AOM)
+    add_definitions(-DAVIF_CODEC_AOM=1)
+    set(AVIF_SRCS ${AVIF_SRCS}
+        src/codec_aom.c
+    )
+    include_directories(
+        "${CMAKE_CURRENT_SOURCE_DIR}/ext/aom"
+        "${AOM_BINARY_DIR}"
+    )
+    set(AVIF_CODEC_LIBARIES ${AVIF_CODEC_LIBARIES} aom)
+endif()
 
 add_library(avif STATIC ${AVIF_SRCS})
-target_link_libraries(avif aom gb)
+target_link_libraries(avif gb ${AVIF_CODEC_LIBARIES})
 
 option(AVIF_BUILD_EXAMPLES "Build avif Examples." OFF)
 if(AVIF_BUILD_EXAMPLES)
@@ -65,32 +70,19 @@
     target_link_libraries(avifdec avif)
 endif()
 
-# Install rules
-if(NOT CMAKE_SKIP_INSTALL_RULES)
-    install(
-        FILES "include/avif/avif.h" "include/avif/internal.h"
-        DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/avif"
-    )
-    install(
-        TARGETS avif
-        DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
-    )
-    if(AVIF_BUILD_APPS)
-        install(
-            TARGETS avifenc avifdec
-            DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}"
-        )
+macro(avif_set_folder_safe target folder)
+    if(TARGET ${target})
+        set_target_properties(${target} PROPERTIES FOLDER ${folder})
     endif()
-endif()
+endmacro()
 
 if(WIN32)
-    # Allow for continuous builders to make a static avif library package
     option(AVIF_BUILD_STATIC "Build static avif library (with codec/gb included)" OFF)
     if(AVIF_BUILD_STATIC)
         add_custom_command(
             OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/avif_static_x64.lib
             COMMAND link.exe /lib /nologo /MACHINE:x64 /OUT:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/avif_static_x64.lib $<TARGET_FILE:avif> $<TARGET_FILE:aom> $<TARGET_FILE:gb>
-            DEPENDS avif aom
+            DEPENDS avif ${AVIF_CODEC_LIBARIES}
             COMMENT "Creating static avif library..."
         )
 
@@ -99,13 +91,8 @@
         )
     endif()
 
-    # Visual Studio organizing
     set_property(GLOBAL PROPERTY USE_FOLDERS ON)
-    macro(avif_set_folder_safe target folder)
-        if(TARGET ${target})
-            set_target_properties(${target} PROPERTIES FOLDER ${folder})
-        endif()
-    endmacro()
+
     avif_set_folder_safe(aom "ext/avif")
     avif_set_folder_safe(aom_av1 "ext/avif")
     avif_set_folder_safe(aom_av1_common "ext/avif")
@@ -149,6 +136,7 @@
     avif_set_folder_safe(aom_version_check "ext/avif")
     avif_set_folder_safe(avif "ext/avif")
     avif_set_folder_safe(dist "ext/avif")
+
     if(NOT AVIF_EXTERNAL_GB)
         avif_set_folder_safe(gb "ext/avif")
     endif()
diff --git a/README.md b/README.md
index 84f9a4f..e2c1f8e 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# libavif [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/louquillio/libavif?branch=master&svg=true)](https://ci.appveyor.com/project/louquillio/libavif) [![Travis Build Status](https://travis-ci.com/AOMediaCodec/libavif.svg?branch=master)](https://travis-ci.com/AOMediaCodec/libavif)
+# libavif [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/joedrago/avif?branch=master&svg=true)](https://ci.appveyor.com/project/joedrago/avif) [![Travis Build Status](https://travis-ci.com/joedrago/avif.svg?branch=master)](https://travis-ci.com/joedrago/avif)
 
 This library aims to be a friendly, portable C implementation of the AV1 Image File Format, as described here:
 
@@ -16,7 +16,7 @@
 
 # Prebuilt Library (Windows)
 
-If you're building on Windows with VS2017 and want to try out libavif without going through the build process, static library builds for both Debug and Release are available on [Appveyor](https://ci.appveyor.com/project/louquillio/libavif).
+If you're building on Windows with VS2017 and want to try out libavif without going through the build process, static library builds for both Debug and Release are available on [Appveyor](https://ci.appveyor.com/project/joedrago/avif).
 
 ---
 
diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt
index 45325c2..9a5e9f5 100644
--- a/ext/CMakeLists.txt
+++ b/ext/CMakeLists.txt
@@ -1,12 +1,14 @@
 # Copyright 2019 Joe Drago. All rights reserved.
 # SPDX-License-Identifier: BSD-2-Clause
 
-set(ENABLE_DOCS 0)
-set(ENABLE_EXAMPLES 0)
-set(ENABLE_TESTDATA 0)
-set(ENABLE_TESTS 0)
-set(ENABLE_TOOLS 0)
-add_subdirectory(aom EXCLUDE_FROM_ALL)
+if(AVIF_CODEC_AOM)
+    set(ENABLE_DOCS 0)
+    set(ENABLE_EXAMPLES 0)
+    set(ENABLE_TESTDATA 0)
+    set(ENABLE_TESTS 0)
+    set(ENABLE_TOOLS 0)
+    add_subdirectory(aom EXCLUDE_FROM_ALL)
+endif()
 
 if(NOT AVIF_EXTERNAL_GB)
 include_directories(gb)
diff --git a/include/avif/avif.h b/include/avif/avif.h
index 54a67cd..12fb80e 100644
--- a/include/avif/avif.h
+++ b/include/avif/avif.h
@@ -93,7 +93,8 @@
     AVIF_RESULT_DECODE_ALPHA_FAILED,
     AVIF_RESULT_COLOR_ALPHA_SIZE_MISMATCH,
     AVIF_RESULT_ISPE_SIZE_MISMATCH,
-    AVIF_UNSUPPORTED_PIXEL_FORMAT
+    AVIF_RESULT_NO_CODEC_AVAILABLE,
+    AVIF_RESULT_
 } avifResult;
 
 const char * avifResultToString(avifResult result);
diff --git a/include/avif/internal.h b/include/avif/internal.h
index 0748ed5..cd4de2f 100644
--- a/include/avif/internal.h
+++ b/include/avif/internal.h
@@ -88,23 +88,33 @@
     uint32_t height;
 } avifCodecImageSize;
 
+struct avifCodec;
 struct avifCodecInternal;
 
+typedef avifBool (* avifCodecDecodeFunc)(struct avifCodec * codec, avifCodecPlanes planes, avifRawData * obu);
+typedef avifCodecImageSize (* avifCodecGetImageSizeFunc)(struct avifCodec * codec, avifCodecPlanes planes); // should return 0s if absent
+typedef avifBool (* avifCodecAlphaLimitedRangeFunc)(struct avifCodec * codec);                              // returns AVIF_TRUE if an alpha plane exists and was encoded with limited range
+typedef avifResult (* avifCodecGetDecodedImageFunc)(struct avifCodec * codec, avifImage * image);
+typedef avifResult (* avifCodecEncodeImageFunc)(struct avifCodec * codec, avifImage * image, avifEncoder * encoder, avifRawData * colorOBU, avifRawData * alphaOBU); // if either OBU* is null, skip its encode. alpha should always be lossless
+typedef void (* avifCodecGetConfigurationBoxFunc)(struct avifCodec * codec, avifCodecPlanes planes, avifCodecConfigurationBox * outConfig);
+typedef void (* avifCodecDestroyInternalFunc)(struct avifCodec * codec);
+
 typedef struct avifCodec
 {
     struct avifCodecInternal * internal; // up to each codec to use how it wants
+
+    avifCodecDecodeFunc decode;
+    avifCodecGetImageSizeFunc getImageSize;
+    avifCodecAlphaLimitedRangeFunc alphaLimitedRange;
+    avifCodecGetDecodedImageFunc getDecodedImage;
+    avifCodecEncodeImageFunc encodeImage;
+    avifCodecGetConfigurationBoxFunc getConfigurationBox;
+    avifCodecDestroyInternalFunc destroyInternal;
 } avifCodec;
 
-avifCodec * avifCodecCreate();
+avifCodec * avifCodecCreateAOM();
 void avifCodecDestroy(avifCodec * codec);
 
-avifBool avifCodecDecode(avifCodec * codec, avifCodecPlanes planes, avifRawData * obu);
-avifCodecImageSize avifCodecGetImageSize(avifCodec * codec, avifCodecPlanes planes); // should return 0s if absent
-avifBool avifCodecAlphaLimitedRange(avifCodec * codec);                              // returns AVIF_TRUE if an alpha plane exists and was encoded with limited range
-avifResult avifCodecGetDecodedImage(avifCodec * codec, avifImage * image);
-avifResult avifCodecEncodeImage(avifCodec * codec, avifImage * image, avifEncoder * encoder, avifRawData * colorOBU, avifRawData * alphaOBU); // if either OBU* is null, skip its encode. alpha should always be lossless
-void avifCodecGetConfigurationBox(avifCodec * codec, avifCodecPlanes planes, avifCodecConfigurationBox * outConfig);
-
 // ---------------------------------------------------------------------------
 // avifStream
 
diff --git a/src/avif.c b/src/avif.c
index 99a9f5b..ffe5e0c 100644
--- a/src/avif.c
+++ b/src/avif.c
@@ -1,7 +1,7 @@
 // Copyright 2019 Joe Drago. All rights reserved.
 // SPDX-License-Identifier: BSD-2-Clause
 
-#include "avif/avif.h"
+#include "avif/internal.h"
 
 #include <string.h>
 
@@ -80,7 +80,7 @@
         case AVIF_RESULT_DECODE_ALPHA_FAILED:       return "Decoding of alpha plane failed";
         case AVIF_RESULT_COLOR_ALPHA_SIZE_MISMATCH: return "Color and alpha planes size mismatch";
         case AVIF_RESULT_ISPE_SIZE_MISMATCH:        return "Plane sizes don't match ispe values";
-        case AVIF_UNSUPPORTED_PIXEL_FORMAT:         return "Unsupported pixel format";
+        case AVIF_RESULT_NO_CODEC_AVAILABLE:        return "No codec available";
         case AVIF_RESULT_UNKNOWN_ERROR:
         default:
             break;
@@ -238,3 +238,13 @@
 {
     return (image->depth > 8) ? AVIF_TRUE : AVIF_FALSE;
 }
+
+// avifCodecCreate*() functions are in their respective codec_*.c files
+
+void avifCodecDestroy(avifCodec * codec)
+{
+    if (codec && codec->destroyInternal) {
+        codec->destroyInternal(codec);
+    }
+    avifFree(codec);
+}
diff --git a/src/codec_aom.c b/src/codec_aom.c
index 97783bd..e715b9c 100644
--- a/src/codec_aom.c
+++ b/src/codec_aom.c
@@ -20,15 +20,7 @@
     avifCodecConfigurationBox configs[AVIF_CODEC_PLANES_COUNT];
 };
 
-avifCodec * avifCodecCreate()
-{
-    avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec));
-    codec->internal = (struct avifCodecInternal *)avifAlloc(sizeof(struct avifCodecInternal));
-    memset(codec->internal, 0, sizeof(struct avifCodecInternal));
-    return codec;
-}
-
-void avifCodecDestroy(avifCodec * codec)
+static void aomCodecDestroyInternal(avifCodec * codec)
 {
     for (int plane = 0; plane < AVIF_CODEC_PLANES_COUNT; ++plane) {
         if (codec->internal->decoderInitialized[plane]) {
@@ -37,10 +29,9 @@
         avifRawDataFree(&codec->internal->encodedOBUs[plane]);
     }
     avifFree(codec->internal);
-    avifFree(codec);
 }
 
-avifBool avifCodecDecode(avifCodec * codec, avifCodecPlanes planes, avifRawData * obu)
+static avifBool aomCodecDecode(avifCodec * codec, avifCodecPlanes planes, avifRawData * obu)
 {
     aom_codec_stream_info_t si;
     aom_codec_iface_t * decoder_interface = aom_codec_av1_dx();
@@ -67,7 +58,7 @@
     return (codec->internal->images[planes]) ? AVIF_TRUE : AVIF_FALSE;
 }
 
-avifCodecImageSize avifCodecGetImageSize(avifCodec * codec, avifCodecPlanes planes)
+static avifCodecImageSize aomCodecGetImageSize(avifCodec * codec, avifCodecPlanes planes)
 {
     avifCodecImageSize size;
     if (codec->internal->images[planes]) {
@@ -80,7 +71,7 @@
     return size;
 }
 
-avifBool avifCodecAlphaLimitedRange(avifCodec * codec)
+static avifBool aomCodecAlphaLimitedRange(avifCodec * codec)
 {
     aom_image_t * aomAlphaImage = codec->internal->images[AVIF_CODEC_PLANES_ALPHA];
     if (aomAlphaImage && (aomAlphaImage->range == AOM_CR_STUDIO_RANGE)) {
@@ -89,7 +80,7 @@
     return AVIF_FALSE;
 }
 
-avifResult avifCodecGetDecodedImage(avifCodec * codec, avifImage * image)
+static avifResult aomCodecGetDecodedImage(avifCodec * codec, avifImage * image)
 {
     aom_image_t * aomColorImage = codec->internal->images[AVIF_CODEC_PLANES_COLOR];
     aom_image_t * aomAlphaImage = codec->internal->images[AVIF_CODEC_PLANES_ALPHA];
@@ -360,7 +351,7 @@
     return success;
 }
 
-avifResult avifCodecEncodeImage(avifCodec * codec, avifImage * image, avifEncoder * encoder, avifRawData * colorOBU, avifRawData * alphaOBU)
+static avifResult aomCodecEncodeImage(avifCodec * codec, avifImage * image, avifEncoder * encoder, avifRawData * colorOBU, avifRawData * alphaOBU)
 {
     if (colorOBU) {
         if (!encodeOBU(image, AVIF_FALSE, encoder, colorOBU, &codec->internal->configs[AVIF_CODEC_PLANES_COLOR])) {
@@ -375,7 +366,24 @@
     return AVIF_RESULT_OK;
 }
 
-void avifCodecGetConfigurationBox(avifCodec * codec, avifCodecPlanes planes, avifCodecConfigurationBox * outConfig)
+static void aomCodecGetConfigurationBox(avifCodec * codec, avifCodecPlanes planes, avifCodecConfigurationBox * outConfig)
 {
     memcpy(outConfig, &codec->internal->configs[planes], sizeof(avifCodecConfigurationBox));
 }
+
+avifCodec * avifCodecCreateAOM()
+{
+    avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec));
+    memset(codec, 0, sizeof(struct avifCodec));
+    codec->decode = aomCodecDecode;
+    codec->getImageSize = aomCodecGetImageSize;
+    codec->alphaLimitedRange = aomCodecAlphaLimitedRange;
+    codec->getDecodedImage = aomCodecGetDecodedImage;
+    codec->encodeImage = aomCodecEncodeImage;
+    codec->getConfigurationBox = aomCodecGetConfigurationBox;
+    codec->destroyInternal = aomCodecDestroyInternal;
+
+    codec->internal = (struct avifCodecInternal *)avifAlloc(sizeof(struct avifCodecInternal));
+    memset(codec->internal, 0, sizeof(struct avifCodecInternal));
+    return codec;
+}
diff --git a/src/read.c b/src/read.c
index a40bc6c..73b97a5 100644
--- a/src/read.c
+++ b/src/read.c
@@ -554,6 +554,11 @@
 {
     avifCodec * codec = NULL;
 
+#ifndef AVIF_CODEC_AOM
+    // Just bail out early, we're not surviving this function without a decoder compiled in
+    return AVIF_RESULT_NO_CODEC_AVAILABLE;
+#endif
+
     // -----------------------------------------------------------------------
     // Parse BMFF boxes
 
@@ -647,21 +652,26 @@
     }
     avifBool hasAlpha = (alphaOBU.size > 0) ? AVIF_TRUE : AVIF_FALSE;
 
-    codec = avifCodecCreate();
-    if (!avifCodecDecode(codec, AVIF_CODEC_PLANES_COLOR, &colorOBU)) {
+#ifdef AVIF_CODEC_AOM
+    codec = avifCodecCreateAOM();
+#else
+// #error No decoder available!
+    return AVIF_RESULT_NO_CODEC_AVAILABLE;
+#endif
+    if (!codec->decode(codec, AVIF_CODEC_PLANES_COLOR, &colorOBU)) {
         avifCodecDestroy(codec);
         return AVIF_RESULT_DECODE_COLOR_FAILED;
     }
-    avifCodecImageSize colorPlanesSize = avifCodecGetImageSize(codec, AVIF_CODEC_PLANES_COLOR);
+    avifCodecImageSize colorPlanesSize = codec->getImageSize(codec, AVIF_CODEC_PLANES_COLOR);
 
     avifCodecImageSize alphaPlanesSize;
     memset(&alphaPlanesSize, 0, sizeof(alphaPlanesSize));
     if (hasAlpha) {
-        if (!avifCodecDecode(codec, AVIF_CODEC_PLANES_ALPHA, &alphaOBU)) {
+        if (!codec->decode(codec, AVIF_CODEC_PLANES_ALPHA, &alphaOBU)) {
             avifCodecDestroy(codec);
             return AVIF_RESULT_DECODE_ALPHA_FAILED;
         }
-        alphaPlanesSize = avifCodecGetImageSize(codec, AVIF_CODEC_PLANES_ALPHA);
+        alphaPlanesSize = codec->getImageSize(codec, AVIF_CODEC_PLANES_ALPHA);
 
         if ((colorPlanesSize.width != alphaPlanesSize.width) || (colorPlanesSize.height != alphaPlanesSize.height)) {
             avifCodecDestroy(codec);
@@ -686,14 +696,14 @@
 
     avifImageFreePlanes(image, AVIF_PLANES_ALL);
 
-    avifResult imageResult = avifCodecGetDecodedImage(codec, image);
+    avifResult imageResult = codec->getDecodedImage(codec, image);
     if (imageResult != AVIF_RESULT_OK) {
         avifCodecDestroy(codec);
         return imageResult;
     }
 
 #if defined(AVIF_FIX_STUDIO_ALPHA)
-    if (hasAlpha && avifCodecAlphaLimitedRange(codec)) {
+    if (hasAlpha && codec->alphaLimitedRange(codec)) {
         // Naughty! Alpha planes are supposed to be full range. Correct that here.
         if (avifImageUsesU16(image)) {
             for (int j = 0; j < image->height; ++j) {
diff --git a/src/write.c b/src/write.c
index 354ef1a..bb3a2d0 100644
--- a/src/write.c
+++ b/src/write.c
@@ -46,7 +46,14 @@
     avifResult result = AVIF_RESULT_UNKNOWN_ERROR;
     avifRawData colorOBU = AVIF_RAW_DATA_EMPTY;
     avifRawData alphaOBU = AVIF_RAW_DATA_EMPTY;
-    avifCodec * codec = avifCodecCreate();
+    avifCodec * codec = NULL;
+
+#ifdef AVIF_CODEC_AOM
+    codec = avifCodecCreateAOM();
+#else
+    // Just bail out early, we're not surviving this function without an encoder compiled in
+    return AVIF_RESULT_NO_CODEC_AVAILABLE;
+#endif
 
     avifStream s;
     avifStreamStart(&s, output);
@@ -81,7 +88,7 @@
         alphaOBUPtr = NULL;
     }
 
-    avifResult encodeResult = avifCodecEncodeImage(codec, image, encoder, &colorOBU, alphaOBUPtr);
+    avifResult encodeResult = codec->encodeImage(codec, image, encoder, &colorOBU, alphaOBUPtr);
     if (encodeResult != AVIF_RESULT_OK) {
         result = encodeResult;
         goto writeCleanup;
@@ -246,7 +253,7 @@
             ipmaPush(&ipmaColor, ipcoIndex);
 
             avifCodecConfigurationBox colorConfig;
-            avifCodecGetConfigurationBox(codec, AVIF_CODEC_PLANES_COLOR, &colorConfig);
+            codec->getConfigurationBox(codec, AVIF_CODEC_PLANES_COLOR, &colorConfig);
             writeConfigBox(&s, &colorConfig);
             ++ipcoIndex;
             ipmaPush(&ipmaColor, ipcoIndex);
@@ -260,7 +267,7 @@
                 ipmaPush(&ipmaAlpha, ipcoIndex);
 
                 avifCodecConfigurationBox alphaConfig;
-                avifCodecGetConfigurationBox(codec, AVIF_CODEC_PLANES_ALPHA, &alphaConfig);
+                codec->getConfigurationBox(codec, AVIF_CODEC_PLANES_ALPHA, &alphaConfig);
                 writeConfigBox(&s, &alphaConfig);
                 ++ipcoIndex;
                 ipmaPush(&ipmaAlpha, ipcoIndex);