summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTOA Developer <justin@boris>2018-03-09 12:00:57 +0100
committerTOA Developer <justin@boris>2018-03-09 12:00:57 +0100
commit4aec59806977e7ee1cb5f837741c6ac47e267330 (patch)
tree7a3696900bd6678593c0178ce5d78ce311c2eba3
parent6cc647b5ce11d8b350a1cf494a8c55245f5e6e5e (diff)
FIXUP WIP CLEANUP CC DECKLINK
-rw-r--r--sys/decklink/gstdecklinkvideosrc.cpp137
-rw-r--r--sys/decklink/gstdecklinkvideosrc.h3
2 files changed, 94 insertions, 46 deletions
diff --git a/sys/decklink/gstdecklinkvideosrc.cpp b/sys/decklink/gstdecklinkvideosrc.cpp
index ed0c47481..770ae7e4d 100644
--- a/sys/decklink/gstdecklinkvideosrc.cpp
+++ b/sys/decklink/gstdecklinkvideosrc.cpp
@@ -36,6 +36,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_decklink_video_src_debug);
#define DEFAULT_OUTPUT_STREAM_TIME (FALSE)
#define DEFAULT_SKIP_FIRST_TIME (0)
#define DEFAULT_DROP_NO_SIGNAL_FRAMES (FALSE)
+#define DEFAULT_OUTPUT_CC (FALSE)
#ifndef ABSDIFF
#define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
@@ -54,7 +55,8 @@ enum
PROP_SKIP_FIRST_TIME,
PROP_DROP_NO_SIGNAL_FRAMES,
PROP_SIGNAL,
- PROP_HW_SERIAL_NUMBER
+ PROP_HW_SERIAL_NUMBER,
+ PROP_OUTPUT_CC
};
typedef struct
@@ -222,6 +224,12 @@ gst_decklink_video_src_class_init (GstDecklinkVideoSrcClass * klass)
"The serial number (hardware ID) of the Decklink card",
NULL, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
+ g_object_class_install_property (gobject_class, PROP_OUTPUT_CC,
+ g_param_spec_boolean ("output-cc", "Output Closed Caption",
+ "Extract and output CC as GstMeta (if present)",
+ DEFAULT_OUTPUT_CC,
+ (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
+
templ_caps = gst_decklink_mode_get_template_caps (TRUE);
gst_element_class_add_pad_template (element_class,
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, templ_caps));
@@ -326,6 +334,9 @@ gst_decklink_video_src_set_property (GObject * object, guint property_id,
case PROP_DROP_NO_SIGNAL_FRAMES:
self->drop_no_signal_frames = g_value_get_boolean (value);
break;
+ case PROP_OUTPUT_CC:
+ self->output_cc = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -376,6 +387,9 @@ gst_decklink_video_src_get_property (GObject * object, guint property_id,
else
g_value_set_string (value, NULL);
break;
+ case PROP_OUTPUT_CC:
+ g_value_set_boolean (value, self->output_cc);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -766,6 +780,79 @@ gst_decklink_video_src_got_frame (GstElement * element,
g_mutex_unlock (&self->lock);
}
+static void
+extract_cc_from_vbi (GstDecklinkVideoSrc * self, GstBuffer ** buffer,
+ VideoFrame * vf, const GstDecklinkMode * mode)
+{
+ IDeckLinkVideoFrameAncillary *vanc_frame = NULL;
+ GstClockTime before = gst_util_get_timestamp ();
+ GstClockTime after;
+ gint fi;
+ guint8 *vancdata;
+ GstVideoFormat videoformat;
+ // FIXME : Move to a central location
+ GstVideoVBIParser *parser = NULL;
+ gboolean found = FALSE;
+
+ if (vf->frame->GetAncillaryData (&vanc_frame) != S_OK)
+ return;
+
+ videoformat =
+ gst_decklink_video_format_from_type (vanc_frame->GetPixelFormat ());
+
+ if (videoformat == GST_VIDEO_FORMAT_UNKNOWN) {
+ GST_DEBUG_OBJECT (self, "Unknown video format for Ancillary data");
+ vanc_frame->Release ();
+ return;
+ }
+
+ GST_DEBUG_OBJECT (self, "Checking for ancillary data in VBI");
+
+ fi = self->last_cc_vbi_line;
+ if (fi == -1)
+ fi = 1;
+
+ while (fi < 22 && !found) {
+ if (vanc_frame->GetBufferForVerticalBlankingLine (fi,
+ (void **) &vancdata) == S_OK) {
+ GstVideoAncillary gstanc;
+ if (parser == NULL)
+ parser = gst_video_vbi_parser_new (videoformat, mode->width);
+ GST_DEBUG_OBJECT (self, "Might have data on line %d", fi);
+ gst_video_vbi_parser_add_line (parser, vancdata);
+
+ while (gst_video_vbi_parser_get_ancillary (parser,
+ &gstanc) == GST_VIDEO_VBI_PARSER_RESULT_OK) {
+ if (GST_VIDEO_ANCILLARY_DID16 (&gstanc) ==
+ GST_VIDEO_ANCILLARY_DID16_S334_EIA_708) {
+ GST_DEBUG_OBJECT (self,
+ "Adding CEA-708 CDP meta to buffer for line %d", fi);
+ GST_MEMDUMP_OBJECT (self, "CDP", gstanc.data, gstanc.data_count);
+ gst_buffer_add_video_caption_meta (*buffer,
+ GST_VIDEO_CAPTION_TYPE_CEA708_CDP, gstanc.data,
+ gstanc.data_count);
+ found = TRUE;
+ self->last_cc_vbi_line = fi;
+ break;
+ }
+ }
+ }
+
+ fi++;
+ }
+
+ if (!found)
+ self->last_cc_vbi_line = -1;
+
+ vanc_frame->Release ();
+ if (parser)
+ gst_video_vbi_parser_free (parser);
+
+ after = gst_util_get_timestamp ();
+ GST_LOG ("Processing ANC took %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (after - before));
+}
+
static GstFlowReturn
gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
{
@@ -858,6 +945,7 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
g_mutex_unlock (&self->lock);
if (caps_changed) {
+ self->last_cc_vbi_line = -1;
caps = gst_decklink_mode_get_caps (f.mode, f.format, TRUE);
gst_video_info_from_caps (&self->info, caps);
gst_base_src_set_caps (GST_BASE_SRC_CAST (bsrc), caps);
@@ -900,51 +988,8 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
mode = gst_decklink_get_mode (self->mode);
- if (1) {
- IDeckLinkVideoFrameAncillary *vanc_frame = NULL;
- if (vf->frame->GetAncillaryData (&vanc_frame) == S_OK) {
- gint fi;
- guint8 *vancdata;
- // guint16 outputdata[2000];
- GstVideoFormat vf;
- // FIXME : Move to a central location
- GstVideoVBIParser *parser = NULL;
-
- vf = gst_decklink_video_format_from_type (vanc_frame->GetPixelFormat ());
-
- if (vf != GST_VIDEO_FORMAT_UNKNOWN) {
- GST_DEBUG_OBJECT (self, "Checking for ancillary data in VBI");
- // FIXME : We are blindly assuming that:
- // 1) The first active video line is 22
- // 2) That there is only one field
- for (fi = 1; fi < 22; fi++) {
- if (vanc_frame->GetBufferForVerticalBlankingLine (fi,
- (void **) &vancdata) == S_OK) {
- GstVideoAncillary gstanc;
- if (parser == NULL)
- parser = gst_video_vbi_parser_new (vf, mode->width);
- GST_DEBUG_OBJECT (self, "Might have data on line %d", fi);
- gst_video_vbi_parser_add_line (parser, vancdata);
- while (gst_video_vbi_parser_get_ancillary (parser,
- &gstanc) == GST_VIDEO_VBI_PARSER_RESULT_OK) {
- if (GST_VIDEO_ANCILLARY_DID16 (&gstanc) ==
- GST_VIDEO_ANCILLARY_DID16_S334_EIA_708) {
- GST_DEBUG_OBJECT (self, "Adding CEA-708 CDP meta to buffer");
- GST_MEMDUMP_OBJECT (self, "CDP", gstanc.data,
- gstanc.data_count);
- gst_buffer_add_video_caption_meta (*buffer,
- GST_VIDEO_CAPTION_TYPE_CEA708_CDP, gstanc.data,
- gstanc.data_count);
- }
- }
- }
- }
- }
- vanc_frame->Release ();
- if (parser)
- gst_video_vbi_parser_free (parser);
- }
- }
+ if (self->output_cc)
+ extract_cc_from_vbi (self, buffer, vf, mode);
if (f.no_signal)
GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_GAP);
diff --git a/sys/decklink/gstdecklinkvideosrc.h b/sys/decklink/gstdecklinkvideosrc.h
index 49c5ba8cf..783e8401e 100644
--- a/sys/decklink/gstdecklinkvideosrc.h
+++ b/sys/decklink/gstdecklinkvideosrc.h
@@ -94,6 +94,9 @@ struct _GstDecklinkVideoSrc
GstClockTime num, den;
} next_time_mapping;
gboolean next_time_mapping_pending;
+
+ gboolean output_cc;
+ guint last_cc_vbi_line;
};
struct _GstDecklinkVideoSrcClass