On 12/29/2017 10:12 AM, Devin Heitmueller wrote:
Make use of libklvanc to parse SCTE-104 packets and announce them
as a new stream.  Right now we just pass the payload straight
through, but once this is hoooked into libklscte35 we'll be able

"hoooked" -> "hooked"

to generate SCTE-35 messages in the MPEG TS stream.

Note that this feature needs to be explicitly enabled by the user
through the "-enable_scte_104" option, since we cannot autodetect
the presence of SCTE-104 (because unlike with 708/AFD messages are
not set except when trigger occurs, thus the stream wouldn't get
created during the read_header phase).

Updated to reflect feedback from Derek Buitenhuis <derek.buitenh...@gmail.com>

Signed-off-by: Devin Heitmueller <dheitmuel...@ltnglobal.com>
---
  libavcodec/avcodec.h            |  1 +
  libavcodec/codec_desc.c         |  6 ++++
  libavdevice/decklink_common.h   |  6 ++++
  libavdevice/decklink_common_c.h |  1 +
  libavdevice/decklink_dec.cpp    | 61 ++++++++++++++++++++++++++++++++++++++++-
  libavdevice/decklink_dec_c.c    |  1 +
  libavdevice/version.h           |  2 +-
  7 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 4f7b6df09d..2b4a0bd669 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -668,6 +668,7 @@ enum AVCodecID {
      AV_CODEC_ID_TTF = 0x18000,
AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream.
+    AV_CODEC_ID_SCTE_104,
      AV_CODEC_ID_BINTEXT    = 0x18800,
      AV_CODEC_ID_XBIN,
      AV_CODEC_ID_IDF,
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index c3688de1d6..e198985bb4 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -3103,6 +3103,12 @@ static const AVCodecDescriptor codec_descriptors[] = {
          .name      = "scte_35",
          .long_name = NULL_IF_CONFIG_SMALL("SCTE 35 Message Queue"),
      },
+    {
+        .id        = AV_CODEC_ID_SCTE_104,
+        .type      = AVMEDIA_TYPE_DATA,
+        .name      = "scte_104",
+        .long_name = NULL_IF_CONFIG_SMALL("SCTE 104 Digital Program 
Insertion"),
+    },
/* deprecated codec ids */
  };
diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
index 06b241029e..4d2052ea79 100644
--- a/libavdevice/decklink_common.h
+++ b/libavdevice/decklink_common.h
@@ -41,6 +41,10 @@
     Actual number for any particular model of card may be lower */
  #define DECKLINK_MAX_AUDIO_CHANNELS 32
+/* This isn't actually tied to the Blackmagic hardware - it's an arbitrary
+   number used to size the array of streams */
+#define DECKLINK_MAX_DATA_STREAMS 16
+
  class decklink_output_callback;
  class decklink_input_callback;
@@ -92,6 +96,8 @@ struct decklink_ctx {
      unsigned int dropped;
      AVStream *audio_st[DECKLINK_MAX_AUDIO_CHANNELS];
      int num_audio_streams;
+    AVStream *data_st[DECKLINK_MAX_DATA_STREAMS];
+    int num_data_streams;
      AVStream *video_st;
      AVStream *teletext_st;
      uint16_t cdp_sequence_num;
diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h
index 02011ed53b..cb73ec990b 100644
--- a/libavdevice/decklink_common_c.h
+++ b/libavdevice/decklink_common_c.h
@@ -58,6 +58,7 @@ struct decklink_cctx {
      char *format_code;
      int raw_format;
      int64_t queue_size;
+    int enable_scte_104;
  };
#endif /* AVDEVICE_DECKLINK_COMMON_C_H */
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 86db6d8fbd..f3f0d989bf 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -672,6 +672,30 @@ error:
      return ret;
  }
+static int setup_data(AVFormatContext *avctx)
+{
+    struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
+    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
+    AVStream *st;
+
+    if (cctx->enable_scte_104) {
+        st = avformat_new_stream(avctx, NULL);
+        if (!st) {
+            av_log(avctx, AV_LOG_ERROR, "Cannot add data stream\n");
+            return AVERROR(ENOMEM);
+        }
+        st->codecpar->codec_type  = AVMEDIA_TYPE_DATA;
+        st->time_base.den         = ctx->bmd_tb_den;
+        st->time_base.num         = ctx->bmd_tb_num;

I wonder if there is any reason to set time_base here. Aren't the triggers relatively infrequent?

+        st->codecpar->codec_id    = AV_CODEC_ID_SCTE_104;
+        avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
+        ctx->data_st[ctx->num_data_streams] = st;
+        ctx->num_data_streams++;
+    }
+
+    return 0;
+}
+
  #if CONFIG_LIBKLVANC
  /* VANC Callbacks */
  struct vanc_cb_ctx {
@@ -731,12 +755,44 @@ static int cb_EIA_708B(void *callback_context, struct 
klvanc_context_s *ctx,
      return 0;
  }
+static int cb_SCTE_104(void *callback_context, struct klvanc_context_s *ctx,
+                       struct klvanc_packet_scte_104_s *pkt)
+{
+    struct vanc_cb_ctx *cb_ctx = (struct vanc_cb_ctx *)callback_context;
+    decklink_cctx *decklink_cctx = (struct decklink_cctx 
*)cb_ctx->avctx->priv_data;
+    struct decklink_ctx *decklink_ctx = (struct decklink_ctx 
*)decklink_cctx->ctx;
+    AVPacket avpkt;
+    av_init_packet(&avpkt);
+
+    avpkt.stream_index = -1;
+    for (int i = 0; i < decklink_ctx->num_data_streams; i++) {
+        if (decklink_ctx->data_st[i]->codecpar->codec_id = 
AV_CODEC_ID_SCTE_104) {
+            avpkt.stream_index = decklink_ctx->data_st[i]->index;
+            break;
+        }
+    }
+    if (avpkt.stream_index == -1) {
+        /* SCTE-104 packet received but forwarding is disabled */
+        return 0;
+    }
+
+    avpkt.pts = cb_ctx->pkt->pts;
+    avpkt.dts = cb_ctx->pkt->dts;
+    avpkt.data = pkt->payload;
+    avpkt.size = pkt->payloadLengthBytes;
+    if (avpacket_queue_put(&decklink_ctx->queue, &avpkt) < 0) {
+        ++decklink_ctx->dropped;
+    }
+
+    return 0;
+}
+
  static struct klvanc_callbacks_s callbacks =
  {
      cb_AFD,
      cb_EIA_708B,
      NULL,
-    NULL,
+    cb_SCTE_104,
      NULL,
      NULL,
  };
@@ -1285,6 +1341,9 @@ av_cold int ff_decklink_read_header(AVFormatContext 
*avctx)
          ctx->teletext_st = st;
      }
+ /* Setup streams. */
+    setup_data(avctx);
+
      if (cctx->audio_mode == AUDIO_MODE_DISCRETE) {
          av_log(avctx, AV_LOG_VERBOSE, "Using %d input audio channels\n", 
ctx->audio_st[0]->codecpar->channels);
          result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz,
diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c
index d3d8c848cf..122da08fa1 100644
--- a/libavdevice/decklink_dec_c.c
+++ b/libavdevice/decklink_dec_c.c
@@ -76,6 +76,7 @@ static const AVOption options[] = {
      { "draw_bars",     "draw bars on signal loss" , OFFSET(draw_bars),    
AV_OPT_TYPE_BOOL,  { .i64 = 1}, 0, 1, DEC },
      { "queue_size",    "input queue buffer size",   OFFSET(queue_size),   
AV_OPT_TYPE_INT64, { .i64 = (1024 * 1024 * 1024)}, 0, INT64_MAX, DEC },
      { "audio_depth",   "audio bitdepth (16 or 32)", OFFSET(audio_depth),  
AV_OPT_TYPE_INT,   { .i64 = 16}, 16, 32, DEC },
+    { "enable_scte_104", "capture SCTE-104 VANC", OFFSET(enable_scte_104), 
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, DEC, "enable_scte_104"},
      { NULL },
  };
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 364404d65e..0d4477f82e 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -29,7 +29,7 @@
#define LIBAVDEVICE_VERSION_MAJOR 58
  #define LIBAVDEVICE_VERSION_MINOR   0
-#define LIBAVDEVICE_VERSION_MICRO 100
+#define LIBAVDEVICE_VERSION_MICRO 101
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
                                                 LIBAVDEVICE_VERSION_MINOR, \


Aaron Levinson
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to