[FFmpeg-devel] [PATCH 2/8] decklink: Add support for output of Active Format Description (AFD)

Devin Heitmueller dheitmueller at ltnglobal.com
Fri Dec 29 20:12:24 EET 2017


Implement support for including AFD in decklink output.  This
includes making sure the AFD data is preserved when going from
an AVFrame to a V210 packet (needed for 10-bit support).

Updated to reflect feedback from Marton Balint <cus at passwd.hu>

Signed-off-by: Devin Heitmueller <dheitmueller at ltnglobal.com>
---
 libavcodec/avcodec.h         |  6 ++++++
 libavcodec/v210enc.c         |  9 +++++++++
 libavdevice/decklink_enc.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 0972df0bde..4f7b6df09d 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1328,6 +1328,12 @@ enum AVPacketSideDataType {
     AV_PKT_DATA_A53_CC,
 
     /**
+     * Active Format Description data consisting of a single byte as specified
+     * in ETSI TS 101 154 using AVActiveFormatDescription enum.
+     */
+    AV_PKT_DATA_AFD,
+
+    /**
      * The number of side data types.
      * This is not part of the public API/ABI in the sense that it may
      * change when new side data types are added.
diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c
index 51804e3bac..26a08a1ec9 100644
--- a/libavcodec/v210enc.c
+++ b/libavcodec/v210enc.c
@@ -243,6 +243,15 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
             return AVERROR(ENOMEM);
     }
 
+    side_data = av_frame_get_side_data(pic, AV_FRAME_DATA_AFD);
+    if (side_data && side_data->size) {
+        uint8_t *buf = av_packet_new_side_data(pkt, AV_PKT_DATA_AFD, side_data->size);
+        if (buf)
+            memcpy(buf, side_data->data, side_data->size);
+        else
+            return AVERROR(ENOMEM);
+    }
+
     pkt->flags |= AV_PKT_FLAG_KEY;
     *got_packet = 1;
     return 0;
diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp
index ded47108d6..59a4181e19 100644
--- a/libavdevice/decklink_enc.cpp
+++ b/libavdevice/decklink_enc.cpp
@@ -284,7 +284,8 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
 
 #if CONFIG_LIBKLVANC
 static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *ctx,
-                                   AVPacket *pkt, decklink_frame *frame)
+                                   AVPacket *pkt, decklink_frame *frame,
+                                   AVStream *st)
 {
     struct klvanc_line_set_s vanc_lines = { 0 };
     int ret, size;
@@ -342,6 +343,46 @@ static int decklink_construct_vanc(AVFormatContext *avctx, struct decklink_ctx *
         }
     }
 
+    data = av_packet_get_side_data(pkt, AV_PKT_DATA_AFD, &size);
+    if (data) {
+        struct klvanc_packet_afd_s *pkt;
+        uint16_t *afd;
+        uint16_t len;
+
+        ret = klvanc_create_AFD(&pkt);
+        if (ret != 0)
+            return AVERROR(ENOMEM);
+
+        ret = klvanc_set_AFD_val(pkt, data[0]);
+        if (ret != 0) {
+            av_log(avctx, AV_LOG_ERROR, "Invalid AFD value specified: %d\n",
+                   data[0]);
+            klvanc_destroy_AFD(pkt);
+            return AVERROR(EINVAL);
+        }
+
+        /* FIXME: Should really rely on the coded_width but seems like that
+           is not accessible to libavdevice outputs */
+        if ((st->codecpar->width == 1280 && st->codecpar->height == 720) ||
+            (st->codecpar->width == 1920 && st->codecpar->height == 1080))
+            pkt->aspectRatio = ASPECT_16x9;
+        else
+            pkt->aspectRatio = ASPECT_4x3;
+
+        ret = klvanc_convert_AFD_to_words(pkt, &afd, &len);
+        if (ret != 0) {
+            av_log(avctx, AV_LOG_ERROR, "Failed converting 708 packet to words\n");
+            return AVERROR(ENOMEM);
+        }
+        klvanc_destroy_AFD(pkt);
+
+        ret = klvanc_line_insert(ctx->vanc_ctx, &vanc_lines, afd, len, 12, 0);
+        if (ret != 0) {
+            av_log(avctx, AV_LOG_ERROR, "VANC line insertion failed\n");
+            return AVERROR(ENOMEM);
+        }
+    }
+
     IDeckLinkVideoFrameAncillary *vanc;
     int result = ctx->dlo->CreateAncillaryData(bmdFormat10BitYUV, &vanc);
     if (result != S_OK) {
@@ -437,7 +478,7 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt)
         frame = new decklink_frame(ctx, avpacket, st->codecpar->codec_id, ctx->bmd_height, ctx->bmd_width);
 
 #if CONFIG_LIBKLVANC
-        ret = decklink_construct_vanc(avctx, ctx, pkt, frame);
+        ret = decklink_construct_vanc(avctx, ctx, pkt, frame, st);
         if (ret != 0) {
             av_log(avctx, AV_LOG_ERROR, "Failed to construct VANC\n");
         }
-- 
2.13.2



More information about the ffmpeg-devel mailing list