diff options
author | TOA Developer <justin@boris> | 2018-03-09 12:00:57 +0100 |
---|---|---|
committer | TOA Developer <justin@boris> | 2018-03-09 12:00:57 +0100 |
commit | 4aec59806977e7ee1cb5f837741c6ac47e267330 (patch) | |
tree | 7a3696900bd6678593c0178ce5d78ce311c2eba3 | |
parent | 6cc647b5ce11d8b350a1cf494a8c55245f5e6e5e (diff) |
FIXUP WIP CLEANUP CC DECKLINK
-rw-r--r-- | sys/decklink/gstdecklinkvideosrc.cpp | 137 | ||||
-rw-r--r-- | sys/decklink/gstdecklinkvideosrc.h | 3 |
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 |