summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2020-11-25 16:24:25 +0200
committerSebastian Dröge <sebastian@centricular.com>2020-12-07 19:23:42 +0200
commit0243afcb9d9a86e6572262d7b0ecb4f108fa147c (patch)
tree9e493d461db82c69ff49357e3ceb26c4d6aff0f6
parentb6debae2c070333b357dfdf2fc4d771ada6b9038 (diff)
downloadgstreamer-plugins-bad-0243afcb9d9a86e6572262d7b0ecb4f108fa147c.tar.gz
ccconverter: Add property to specify which sections to include in CDP packets
Various software, including ffmpeg's Decklink support, fails parsing CDP packets that contain anything but CC data in the CDP packets. Based on this property, timecodes are not written into the CDP packets even if they're present. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1833>
-rw-r--r--docs/plugins/gst_plugins_cache.json35
-rw-r--r--ext/closedcaption/gstccconverter.c132
-rw-r--r--ext/closedcaption/gstccconverter.h8
3 files changed, 162 insertions, 13 deletions
diff --git a/docs/plugins/gst_plugins_cache.json b/docs/plugins/gst_plugins_cache.json
index 5248eb83b..71d8f72c4 100644
--- a/docs/plugins/gst_plugins_cache.json
+++ b/docs/plugins/gst_plugins_cache.json
@@ -3346,7 +3346,20 @@
"presence": "always"
}
},
- "properties": {},
+ "properties": {
+ "cdp-mode": {
+ "blurb": "Select which CDP sections to store in CDP packets",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "cc-svc-info+cc-data+time-code",
+ "mutable": "null",
+ "readable": true,
+ "type": "GstCCConverterCDPMode",
+ "writable": true
+ }
+ },
"rank": "none"
},
"ccextractor": {
@@ -3470,6 +3483,26 @@
"filename": "gstclosedcaption",
"license": "LGPL",
"other-types": {
+ "GstCCConverterCDPMode": {
+ "kind": "flags",
+ "values": [
+ {
+ "desc": "Store time code information in CDP packets",
+ "name": "time-code",
+ "value": "0x00000001"
+ },
+ {
+ "desc": "Store CC data in CDP packets",
+ "name": "cc-data",
+ "value": "0x00000002"
+ },
+ {
+ "desc": "Store CC service information in CDP packets",
+ "name": "cc-svc-info",
+ "value": "0x00000004"
+ }
+ ]
+ },
"GstCeaCcOverlayWinHPos": {
"kind": "enum",
"values": [
diff --git a/ext/closedcaption/gstccconverter.c b/ext/closedcaption/gstccconverter.c
index 43073fb3f..fe6aadd4c 100644
--- a/ext/closedcaption/gstccconverter.c
+++ b/ext/closedcaption/gstccconverter.c
@@ -33,6 +33,23 @@
GST_DEBUG_CATEGORY_STATIC (gst_cc_converter_debug);
#define GST_CAT_DEFAULT gst_cc_converter_debug
+/**
+ * GstCCConverterCDPMode:
+ * @GST_CC_CONVERTER_CDP_MODE_TIME_CODE: Store time code information in CDP packets
+ * @GST_CC_CONVERTER_CDP_MODE_CC_DATA: Store CC data in CDP packets
+ * @GST_CC_CONVERTER_CDP_MODE_CC_SVC_INFO: Store CC service information in CDP packets
+ *
+ * Since: 1.20
+ */
+
+enum
+{
+ PROP_0,
+ PROP_CDP_MODE,
+};
+
+#define DEFAULT_CDP_MODE (GST_CC_CONVERTER_CDP_MODE_TIME_CODE | GST_CC_CONVERTER_CDP_MODE_CC_DATA | GST_CC_CONVERTER_CDP_MODE_CC_SVC_INFO)
+
/* Ordered by the amount of information they can contain */
#define CC_CAPS \
"closedcaption/x-cea-708,format=(string) cdp; " \
@@ -55,6 +72,32 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
G_DEFINE_TYPE (GstCCConverter, gst_cc_converter, GST_TYPE_BASE_TRANSFORM);
#define parent_class gst_cc_converter_parent_class
+#define GST_TYPE_CC_CONVERTER_CDP_MODE (gst_cc_converter_cdp_mode_get_type())
+static GType
+gst_cc_converter_cdp_mode_get_type (void)
+{
+ static const GFlagsValue values[] = {
+ {GST_CC_CONVERTER_CDP_MODE_TIME_CODE,
+ "Store time code information in CDP packets", "time-code"},
+ {GST_CC_CONVERTER_CDP_MODE_CC_DATA, "Store CC data in CDP packets",
+ "cc-data"},
+ {GST_CC_CONVERTER_CDP_MODE_CC_SVC_INFO,
+ "Store CC service information in CDP packets", "cc-svc-info"},
+ {0, NULL, NULL}
+ };
+ static volatile GType id = 0;
+
+ if (g_once_init_enter ((gsize *) & id)) {
+ GType _id;
+
+ _id = g_flags_register_static ("GstCCConverterCDPMode", values);
+
+ g_once_init_leave ((gsize *) & id, _id);
+ }
+
+ return id;
+}
+
static gboolean
gst_cc_converter_transform_size (GstBaseTransform * base,
GstPadDirection direction,
@@ -1001,11 +1044,16 @@ convert_cea708_cc_data_cea708_cdp_internal (GstCCConverter * self,
cc_data_len = 3 * fps_entry->max_cc_count;
}
- /* ccdata_present | caption_service_active */
- flags = 0x42;
+ /* caption_service_active */
+ flags = 0x02;
+
+ /* ccdata_present */
+ if ((self->cdp_mode & GST_CC_CONVERTER_CDP_MODE_CC_DATA))
+ flags |= 0x40;
/* time_code_present */
- if (tc && tc->config.fps_n > 0)
+ if ((self->cdp_mode & GST_CC_CONVERTER_CDP_MODE_TIME_CODE) && tc
+ && tc->config.fps_n > 0)
flags |= 0x80;
/* reserved */
@@ -1015,7 +1063,8 @@ convert_cea708_cc_data_cea708_cdp_internal (GstCCConverter * self,
gst_byte_writer_put_uint16_be_unchecked (&bw, self->cdp_hdr_sequence_cntr);
- if (tc && tc->config.fps_n > 0) {
+ if ((self->cdp_mode & GST_CC_CONVERTER_CDP_MODE_TIME_CODE) && tc
+ && tc->config.fps_n > 0) {
guint8 u8;
gst_byte_writer_put_uint8_unchecked (&bw, 0x71);
@@ -1054,14 +1103,16 @@ convert_cea708_cc_data_cea708_cdp_internal (GstCCConverter * self,
gst_byte_writer_put_uint8_unchecked (&bw, u8);
}
- gst_byte_writer_put_uint8_unchecked (&bw, 0x72);
- gst_byte_writer_put_uint8_unchecked (&bw, 0xe0 | fps_entry->max_cc_count);
- gst_byte_writer_put_data_unchecked (&bw, cc_data, cc_data_len);
- while (fps_entry->max_cc_count > cc_data_len / 3) {
- gst_byte_writer_put_uint8_unchecked (&bw, 0xfa);
- gst_byte_writer_put_uint8_unchecked (&bw, 0x00);
- gst_byte_writer_put_uint8_unchecked (&bw, 0x00);
- cc_data_len += 3;
+ if ((self->cdp_mode & GST_CC_CONVERTER_CDP_MODE_CC_DATA)) {
+ gst_byte_writer_put_uint8_unchecked (&bw, 0x72);
+ gst_byte_writer_put_uint8_unchecked (&bw, 0xe0 | fps_entry->max_cc_count);
+ gst_byte_writer_put_data_unchecked (&bw, cc_data, cc_data_len);
+ while (fps_entry->max_cc_count > cc_data_len / 3) {
+ gst_byte_writer_put_uint8_unchecked (&bw, 0xfa);
+ gst_byte_writer_put_uint8_unchecked (&bw, 0x00);
+ gst_byte_writer_put_uint8_unchecked (&bw, 0x00);
+ cc_data_len += 3;
+ }
}
gst_byte_writer_put_uint8_unchecked (&bw, 0x74);
@@ -2436,14 +2487,68 @@ gst_cc_converter_stop (GstBaseTransform * base)
}
static void
+gst_cc_converter_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstCCConverter *filter = GST_CCCONVERTER (object);
+
+ switch (prop_id) {
+ case PROP_CDP_MODE:
+ filter->cdp_mode = g_value_get_flags (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_cc_converter_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstCCConverter *filter = GST_CCCONVERTER (object);
+
+ switch (prop_id) {
+ case PROP_CDP_MODE:
+ g_value_set_flags (value, filter->cdp_mode);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
gst_cc_converter_class_init (GstCCConverterClass * klass)
{
+ GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseTransformClass *basetransform_class;
+ gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
basetransform_class = (GstBaseTransformClass *) klass;
+ gobject_class->set_property = gst_cc_converter_set_property;
+ gobject_class->get_property = gst_cc_converter_get_property;
+
+ /**
+ * GstCCConverter:cdp-mode
+ *
+ * Only insert the selection sections into CEA 708 CDP packets.
+ *
+ * Various software does not handle any other information than CC data
+ * contained in CDP packets and might fail parsing the packets otherwise.
+ *
+ * Since: 1.20
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (klass),
+ PROP_CDP_MODE, g_param_spec_flags ("cdp-mode",
+ "CDP Mode",
+ "Select which CDP sections to store in CDP packets",
+ GST_TYPE_CC_CONVERTER_CDP_MODE, DEFAULT_CDP_MODE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gst_element_class_set_static_metadata (gstelement_class,
"Closed Caption Converter",
"Filter/ClosedCaption",
@@ -2472,9 +2577,12 @@ gst_cc_converter_class_init (GstCCConverterClass * klass)
GST_DEBUG_CATEGORY_INIT (gst_cc_converter_debug, "ccconverter",
0, "Closed Caption converter");
+
+ gst_type_mark_as_plugin_api (GST_TYPE_CC_CONVERTER_CDP_MODE, 0);
}
static void
gst_cc_converter_init (GstCCConverter * self)
{
+ self->cdp_mode = DEFAULT_CDP_MODE;
}
diff --git a/ext/closedcaption/gstccconverter.h b/ext/closedcaption/gstccconverter.h
index 7ed6e4285..752988917 100644
--- a/ext/closedcaption/gstccconverter.h
+++ b/ext/closedcaption/gstccconverter.h
@@ -43,10 +43,18 @@ typedef struct _GstCCConverterClass GstCCConverterClass;
#define MAX_CDP_PACKET_LEN 256
#define MAX_CEA608_LEN 32
+typedef enum {
+ GST_CC_CONVERTER_CDP_MODE_TIME_CODE = (1<<0),
+ GST_CC_CONVERTER_CDP_MODE_CC_DATA = (1<<1),
+ GST_CC_CONVERTER_CDP_MODE_CC_SVC_INFO = (1<<2)
+} GstCCConverterCDPMode;
+
struct _GstCCConverter
{
GstBaseTransform parent;
+ GstCCConverterCDPMode cdp_mode;
+
GstVideoCaptionType input_caption_type;
GstVideoCaptionType output_caption_type;