mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
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>
This commit is contained in:
parent
b6debae2c0
commit
0243afcb9d
3 changed files with 162 additions and 13 deletions
|
@ -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": [
|
||||
|
|
|
@ -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);
|
||||
|
@ -2435,15 +2486,69 @@ gst_cc_converter_stop (GstBaseTransform * base)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue