Roll "singleImage" and keyframe forcing into a flags value, add keyframe interval feature with a sensible default in avifenc
diff --git a/src/codec_aom.c b/src/codec_aom.c
index 7802d6d..a23e0cc 100644
--- a/src/codec_aom.c
+++ b/src/codec_aom.c
@@ -239,7 +239,7 @@
                                     const avifImage * image,
                                     avifEncoder * encoder,
                                     avifBool alpha,
-                                    avifBool forceKeyframe,
+                                    uint32_t addImageFlags,
                                     avifCodecEncodeOutput * output)
 {
     if (!codec->internal->encoderInitialized) {
@@ -398,7 +398,7 @@
     }
 
     aom_enc_frame_flags_t encodeFlags = 0;
-    if (forceKeyframe) {
+    if (addImageFlags & AVIF_ADD_IMAGE_FLAG_FORCE_KEYFRAME) {
         encodeFlags |= AOM_EFLAG_FORCE_KF;
     }
     aom_codec_encode(&codec->internal->encoder, aomImage, 0, 1, encodeFlags);
diff --git a/src/codec_rav1e.c b/src/codec_rav1e.c
index 9cdf133..b765159 100644
--- a/src/codec_rav1e.c
+++ b/src/codec_rav1e.c
@@ -35,7 +35,7 @@
                                       const avifImage * image,
                                       avifEncoder * encoder,
                                       avifBool alpha,
-                                      avifBool forceKeyframe,
+                                      uint32_t addImageFlags,
                                       avifCodecEncodeOutput * output)
 {
     avifBool success = AVIF_FALSE;
@@ -79,7 +79,7 @@
             goto cleanup;
         }
 
-        if (encoder->singleImage) {
+        if (addImageFlags & AVIF_ADD_IMAGE_FLAG_SINGLE) {
             if (rav1e_config_parse(rav1eConfig, "still_picture", "true") == -1) {
                 goto cleanup;
             }
@@ -153,7 +153,7 @@
     }
 
     RaFrameTypeOverride frameType = RA_FRAME_TYPE_OVERRIDE_NO;
-    if (forceKeyframe) {
+    if (addImageFlags & AVIF_ADD_IMAGE_FLAG_FORCE_KEYFRAME) {
         frameType = RA_FRAME_TYPE_OVERRIDE_KEY;
     }
     rav1e_frame_set_type(rav1eFrame, frameType);
diff --git a/src/write.c b/src/write.c
index b666d65..1c94e65 100644
--- a/src/write.c
+++ b/src/write.c
@@ -177,7 +177,7 @@
     encoder->speed = AVIF_SPEED_DEFAULT;
     encoder->data = avifEncoderDataCreate();
     encoder->timescale = 1;
-    encoder->singleImage = AVIF_FALSE;
+    encoder->keyframeInterval = 0;
     return encoder;
 }
 
@@ -332,7 +332,7 @@
     avifRWStreamFinishBox(s, meta);
 }
 
-avifResult avifEncoderAddImage(avifEncoder * encoder, const avifImage * image, uint64_t durationInTimescales)
+avifResult avifEncoderAddImage(avifEncoder * encoder, const avifImage * image, uint64_t durationInTimescales, uint32_t addImageFlags)
 {
     // -----------------------------------------------------------------------
     // Validate image
@@ -446,15 +446,14 @@
     // -----------------------------------------------------------------------
     // Encode AV1 OBUs
 
-    avifBool forceKeyframe = AVIF_FALSE;
-    if ((encoder->data->frames.count % 8) == 0) { // TODO: make this configurable
-        forceKeyframe = AVIF_TRUE;
+    if (encoder->keyframeInterval && ((encoder->data->frames.count % encoder->keyframeInterval) == 0)) {
+        addImageFlags |= AVIF_ADD_IMAGE_FLAG_FORCE_KEYFRAME;
     }
 
     for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) {
         avifEncoderItem * item = &encoder->data->items.item[itemIndex];
         if (item->codec) {
-            if (!item->codec->encodeImage(item->codec, image, encoder, item->alpha, forceKeyframe, item->encodeOutput)) {
+            if (!item->codec->encodeImage(item->codec, image, encoder, item->alpha, addImageFlags, item->encodeOutput)) {
                 return item->alpha ? AVIF_RESULT_ENCODE_ALPHA_FAILED : AVIF_RESULT_ENCODE_COLOR_FAILED;
             }
         }
@@ -956,8 +955,7 @@
 
 avifResult avifEncoderWrite(avifEncoder * encoder, const avifImage * image, avifRWData * output)
 {
-    encoder->singleImage = AVIF_TRUE;
-    avifResult addImageResult = avifEncoderAddImage(encoder, image, 1);
+    avifResult addImageResult = avifEncoderAddImage(encoder, image, 1, AVIF_ADD_IMAGE_FLAG_SINGLE);
     if (addImageResult != AVIF_RESULT_OK) {
         return addImageResult;
     }