cccombiner: expose output-padding property

When schedule=true and output-padding=false, cccombiner will not
inject padding in the output closed caption meta stream.

The property has no effect when schedule=false.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1621>
This commit is contained in:
Mathieu Duponchelle 2022-02-01 23:46:43 +01:00 committed by GStreamer Marge Bot
parent db5a4b490d
commit f10e2eb88f
3 changed files with 59 additions and 7 deletions

View file

@ -4952,6 +4952,18 @@
"type": "guint", "type": "guint",
"writable": true "writable": true
}, },
"output-padding": {
"blurb": "Whether to output padding packets when schedule=true",
"conditionally-available": false,
"construct": false,
"construct-only": false,
"controllable": false,
"default": "true",
"mutable": "ready",
"readable": true,
"type": "gboolean",
"writable": true
},
"schedule": { "schedule": {
"blurb": "Schedule caption buffers so that exactly one is output per video frame", "blurb": "Schedule caption buffers so that exactly one is output per video frame",
"conditionally-available": false, "conditionally-available": false,

View file

@ -60,11 +60,13 @@ enum
{ {
PROP_0, PROP_0,
PROP_SCHEDULE, PROP_SCHEDULE,
PROP_OUTPUT_PADDING,
PROP_MAX_SCHEDULED, PROP_MAX_SCHEDULED,
}; };
#define DEFAULT_MAX_SCHEDULED 30 #define DEFAULT_MAX_SCHEDULED 30
#define DEFAULT_SCHEDULE TRUE #define DEFAULT_SCHEDULE TRUE
#define DEFAULT_OUTPUT_PADDING TRUE
typedef struct typedef struct
{ {
@ -689,7 +691,7 @@ dequeue_caption_one_field (GstCCCombiner * self, const GstVideoTimeCode * tc,
caption_data.buffer = scheduled->buffer; caption_data.buffer = scheduled->buffer;
caption_data.caption_type = self->caption_type; caption_data.caption_type = self->caption_type;
g_array_append_val (self->current_frame_captions, caption_data); g_array_append_val (self->current_frame_captions, caption_data);
} else if (!drain) { } else if (!drain && self->output_padding) {
caption_data.caption_type = self->caption_type; caption_data.caption_type = self->caption_type;
caption_data.buffer = make_padding (self, tc, field); caption_data.buffer = make_padding (self, tc, field);
g_array_append_val (self->current_frame_captions, caption_data); g_array_append_val (self->current_frame_captions, caption_data);
@ -701,7 +703,7 @@ dequeue_caption_both_fields (GstCCCombiner * self, const GstVideoTimeCode * tc,
gboolean drain) gboolean drain)
{ {
CaptionQueueItem *field0_scheduled, *field1_scheduled; CaptionQueueItem *field0_scheduled, *field1_scheduled;
GstBuffer *field0_buffer, *field1_buffer; GstBuffer *field0_buffer = NULL, *field1_buffer = NULL;
CaptionData caption_data; CaptionData caption_data;
field0_scheduled = gst_queue_array_pop_head_struct (self->scheduled[0]); field0_scheduled = gst_queue_array_pop_head_struct (self->scheduled[0]);
@ -713,21 +715,32 @@ dequeue_caption_both_fields (GstCCCombiner * self, const GstVideoTimeCode * tc,
if (field0_scheduled) { if (field0_scheduled) {
field0_buffer = field0_scheduled->buffer; field0_buffer = field0_scheduled->buffer;
} else { } else if (self->output_padding) {
field0_buffer = make_padding (self, tc, 0); field0_buffer = make_padding (self, tc, 0);
} }
if (field1_scheduled) { if (field1_scheduled) {
field1_buffer = field1_scheduled->buffer; field1_buffer = field1_scheduled->buffer;
} else { } else if (self->output_padding) {
field1_buffer = make_padding (self, tc, 1); field1_buffer = make_padding (self, tc, 1);
} }
caption_data.caption_type = self->caption_type; if (field0_buffer || field1_buffer) {
if (field0_buffer && field1_buffer) {
caption_data.buffer = gst_buffer_append (field0_buffer, field1_buffer); caption_data.buffer = gst_buffer_append (field0_buffer, field1_buffer);
} else if (field0_buffer) {
caption_data.buffer = field0_buffer;
} else if (field1_buffer) {
caption_data.buffer = field1_buffer;
} else {
g_assert_not_reached ();
}
caption_data.caption_type = self->caption_type;
g_array_append_val (self->current_frame_captions, caption_data); g_array_append_val (self->current_frame_captions, caption_data);
} }
}
static GstFlowReturn static GstFlowReturn
gst_cc_combiner_collect_captions (GstCCCombiner * self, gboolean timeout) gst_cc_combiner_collect_captions (GstCCCombiner * self, gboolean timeout)
@ -1419,6 +1432,7 @@ gst_cc_combiner_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_PAUSED:
self->schedule = self->prop_schedule; self->schedule = self->prop_schedule;
self->max_scheduled = self->prop_max_scheduled; self->max_scheduled = self->prop_max_scheduled;
self->output_padding = self->prop_output_padding;
break; break;
default: default:
break; break;
@ -1440,6 +1454,9 @@ gst_cc_combiner_set_property (GObject * object, guint prop_id,
case PROP_MAX_SCHEDULED: case PROP_MAX_SCHEDULED:
self->prop_max_scheduled = g_value_get_uint (value); self->prop_max_scheduled = g_value_get_uint (value);
break; break;
case PROP_OUTPUT_PADDING:
self->prop_output_padding = g_value_get_boolean (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -1459,6 +1476,9 @@ gst_cc_combiner_get_property (GObject * object, guint prop_id, GValue * value,
case PROP_MAX_SCHEDULED: case PROP_MAX_SCHEDULED:
g_value_set_uint (value, self->prop_max_scheduled); g_value_set_uint (value, self->prop_max_scheduled);
break; break;
case PROP_OUTPUT_PADDING:
g_value_set_boolean (value, self->prop_output_padding);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -1536,6 +1556,23 @@ gst_cc_combiner_class_init (GstCCCombinerClass * klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_READY)); GST_PARAM_MUTABLE_READY));
/**
* GstCCCombiner:output-padding:
*
* When #GstCCCombiner:schedule is %TRUE, this property controls
* whether the output closed caption meta stream will be padded.
*
* Since: 1.22
*/
g_object_class_install_property (G_OBJECT_CLASS (klass),
PROP_OUTPUT_PADDING, g_param_spec_boolean ("output-padding",
"Output padding",
"Whether to output padding packets when schedule=true",
DEFAULT_OUTPUT_PADDING,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_READY));
gst_element_class_add_static_pad_template_with_gtype (gstelement_class, gst_element_class_add_static_pad_template_with_gtype (gstelement_class,
&sinktemplate, GST_TYPE_AGGREGATOR_PAD); &sinktemplate, GST_TYPE_AGGREGATOR_PAD);
gst_element_class_add_static_pad_template_with_gtype (gstelement_class, gst_element_class_add_static_pad_template_with_gtype (gstelement_class,
@ -1585,6 +1622,7 @@ gst_cc_combiner_init (GstCCCombiner * self)
self->prop_schedule = DEFAULT_SCHEDULE; self->prop_schedule = DEFAULT_SCHEDULE;
self->prop_max_scheduled = DEFAULT_MAX_SCHEDULED; self->prop_max_scheduled = DEFAULT_MAX_SCHEDULED;
self->prop_output_padding = DEFAULT_OUTPUT_PADDING;
self->scheduled[0] = self->scheduled[0] =
gst_queue_array_new_for_struct (sizeof (CaptionQueueItem), 0); gst_queue_array_new_for_struct (sizeof (CaptionQueueItem), 0);
self->scheduled[1] = self->scheduled[1] =

View file

@ -65,9 +65,11 @@ struct _GstCCCombiner
gboolean prop_schedule; gboolean prop_schedule;
guint prop_max_scheduled; guint prop_max_scheduled;
gboolean prop_output_padding;
gboolean schedule; gboolean schedule;
guint max_scheduled; guint max_scheduled;
gboolean output_padding;
/* One queue per field */ /* One queue per field */
GstQueueArray *scheduled[2]; GstQueueArray *scheduled[2];
guint16 cdp_hdr_sequence_cntr; guint16 cdp_hdr_sequence_cntr;