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; " \
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,
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 */
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);
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);
}
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",
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;
}