diff --git a/libavdevice/Makefile b/libavdevice/Makefile
index 8a62822..c304492 100644
--- a/libavdevice/Makefile
+++ b/libavdevice/Makefile
@@ -57,6 +57,7 @@ OBJS-$(CONFIG_LIBDC1394_INDEV)           += libdc1394.o
 
 # Objects duplicated from other libraries for shared builds
 SHLIBOBJS-$(CONFIG_DECKLINK_INDEV)       += reverse.o
+SHLIBOBJS-$(CONFIG_DECKLINK_OUTDEV)      += ccfifo.o
 
 # Windows resource file
 SHLIBOBJS-$(HAVE_GNU_WINDRES)            += avdeviceres.o
diff --git a/libavdevice/ccfifo.c b/libavdevice/ccfifo.c
new file mode 100644
index 0000000..9007094
--- /dev/null
+++ b/libavdevice/ccfifo.c
@@ -0,0 +1,24 @@
+/*
+ * CEA-708 Closed Captioning FIFO
+ * Copyright (c) 2023 LTN Global Communications
+ *
+ * Author: Devin Heitmueller <dheitmueller@ltnglobal.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavfilter/ccfifo.c"
diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
index 088e165..0d33f94 100644
--- a/libavdevice/decklink_common.h
+++ b/libavdevice/decklink_common.h
@@ -31,6 +31,7 @@
 
 extern "C" {
 #include "libavcodec/packet_internal.h"
+#include "libavfilter/ccfifo.h"
 }
 #include "libavutil/thread.h"
 #include "decklink_common_c.h"
@@ -112,6 +113,8 @@ struct decklink_ctx {
     /* Capture buffer queue */
     AVPacketQueue queue;
 
+    AVCCFifo *cc_fifo;      ///< closed captions
+
     /* Streams present */
     int audio;
     int video;
diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp
index 9f1a8df..22aa80b 100644
--- a/libavdevice/decklink_enc.cpp
+++ b/libavdevice/decklink_enc.cpp
@@ -326,6 +326,25 @@ static int create_s337_payload(AVPacket *pkt, uint8_t **outbuf, int *outsize)
     return 0;
 }
 
+static int decklink_setup_subtitle(AVFormatContext *avctx, AVStream *st)
+{
+    int ret = -1;
+
+    switch(st->codecpar->codec_id) {
+#if CONFIG_LIBKLVANC
+    case AV_CODEC_ID_EIA_608:
+        /* No special setup required */
+        ret = 0;
+        break;
+#endif
+    default:
+        av_log(avctx, AV_LOG_ERROR, "Unsupported subtitle codec specified\n");
+        break;
+    }
+
+    return ret;
+}
+
 av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
 {
     struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
@@ -352,6 +371,7 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
     klvanc_context_destroy(ctx->vanc_ctx);
 #endif
 
+    ff_ccfifo_freep(&ctx->cc_fifo);
     av_freep(&cctx->ctx);
 
     return 0;
@@ -503,6 +523,21 @@ out:
         free(afd_words);
 }
 
+/* Parse any EIA-608 subtitles sitting on the queue, and write packet side data
+   that will later be handled by construct_cc... */
+static void parse_608subs(AVFormatContext *avctx, struct decklink_ctx *ctx, AVPacket *pkt)
+{
+    size_t cc_size = ff_ccfifo_getoutputsize(ctx->cc_fifo);
+    uint8_t *cc_data;
+
+    if (!ff_ccfifo_ccdetected(ctx->cc_fifo))
+        return;
+
+    cc_data = av_packet_new_side_data(pkt, AV_PKT_DATA_A53_CC, cc_size);
+    if (cc_data)
+        ff_ccfifo_injectbytes(ctx->cc_fifo, cc_data, cc_size);
+}
+
 static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *ctx,
                                    AVPacket *pkt, decklink_frame *frame,
                                    AVStream *st)
@@ -513,6 +548,7 @@ static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *
     if (!ctx->supports_vanc)
         return 0;
 
+    parse_608subs(avctx, ctx, pkt);
     construct_cc(avctx, ctx, pkt, &vanc_lines);
     construct_afd(avctx, ctx, pkt, &vanc_lines, st);
 
@@ -704,6 +740,16 @@ static int decklink_write_audio_packet(AVFormatContext *avctx, AVPacket *pkt)
     return ret;
 }
 
+static int decklink_write_subtitle_packet(AVFormatContext *avctx, AVPacket *pkt)
+{
+    struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
+    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
+
+    ff_ccfifo_extractbytes(ctx->cc_fifo, pkt->data, pkt->size);
+
+    return 0;
+}
+
 extern "C" {
 
 av_cold int ff_decklink_write_header(AVFormatContext *avctx)
@@ -768,12 +814,29 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
         } else if (c->codec_type == AVMEDIA_TYPE_VIDEO) {
             if (decklink_setup_video(avctx, st))
                 goto error;
+        } else if (c->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+            if (decklink_setup_subtitle(avctx, st))
+                goto error;
         } else {
             av_log(avctx, AV_LOG_ERROR, "Unsupported stream type.\n");
             goto error;
         }
     }
 
+    for (n = 0; n < avctx->nb_streams; n++) {
+        AVStream *st = avctx->streams[n];
+        AVCodecParameters *c = st->codecpar;
+
+        if(c->codec_type == AVMEDIA_TYPE_SUBTITLE)
+            avpriv_set_pts_info(st, 64, ctx->bmd_tb_num, ctx->bmd_tb_den);
+    }
+
+    if (!(ctx->cc_fifo = ff_ccfifo_alloc(av_make_q(ctx->bmd_tb_den, ctx->bmd_tb_num), avctx))) {
+        av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n");
+        ret = AVERROR(ENOMEM);
+        goto error;
+    }
+
     return 0;
 
 error:
@@ -789,6 +852,8 @@ int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt)
         return decklink_write_video_packet(avctx, pkt);
     else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
         return decklink_write_audio_packet(avctx, pkt);
+    else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
+        return decklink_write_subtitle_packet(avctx, pkt);
 
     return AVERROR(EIO);
 }
diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c
index f7e3150..0a3984b 100644
--- a/libavdevice/decklink_enc_c.c
+++ b/libavdevice/decklink_enc_c.c
@@ -77,7 +77,7 @@ const FFOutputFormat ff_decklink_muxer = {
     .p.long_name      = NULL_IF_CONFIG_SMALL("Blackmagic DeckLink output"),
     .p.audio_codec    = AV_CODEC_ID_PCM_S16LE,
     .p.video_codec    = AV_CODEC_ID_WRAPPED_AVFRAME,
-    .p.subtitle_codec = AV_CODEC_ID_NONE,
+    .p.subtitle_codec = AV_CODEC_ID_EIA_608,
     .p.flags          = AVFMT_NOFILE,
     .p.priv_class     = &decklink_muxer_class,
     .get_device_list = ff_decklink_list_output_devices,
