|
@@ -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);
|
|
|
}
|