21
21
* SECTION:element-output-selector
22
* @short_description: 1-to-N stream selectoring
23
22
* @see_also: #GstTee, #GstInputSelector
25
24
* Direct input stream to one out of N output pads.
64
GST_BOILERPLATE (GstOutputSelector, gst_output_selector, GstElement,
63
67
static void gst_output_selector_dispose (GObject * object);
64
static void gst_output_selector_init (GstOutputSelector * sel);
65
static void gst_output_selector_base_init (GstOutputSelectorClass * klass);
66
static void gst_output_selector_class_init (GstOutputSelectorClass * klass);
67
68
static void gst_output_selector_set_property (GObject * object,
68
69
guint prop_id, const GValue * value, GParamSpec * pspec);
69
70
static void gst_output_selector_get_property (GObject * object,
78
79
static gboolean gst_output_selector_handle_sink_event (GstPad * pad,
81
static GstElementClass *parent_class = NULL;
84
gst_output_selector_get_type (void)
86
static GType output_selector_type = 0;
88
if (!output_selector_type) {
89
static const GTypeInfo output_selector_info = {
90
sizeof (GstOutputSelectorClass),
91
(GBaseInitFunc) gst_output_selector_base_init,
93
(GClassInitFunc) gst_output_selector_class_init,
96
sizeof (GstOutputSelector),
98
(GInstanceInitFunc) gst_output_selector_init,
100
output_selector_type =
101
g_type_register_static (GST_TYPE_ELEMENT,
102
"GstOutputSelector", &output_selector_info, 0);
103
GST_DEBUG_CATEGORY_INIT (output_selector_debug,
104
"output-selector", 0, "An output stream selector element");
107
return output_selector_type;
111
gst_output_selector_base_init (GstOutputSelectorClass * klass)
83
gst_output_selector_base_init (gpointer g_class)
113
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
85
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
115
87
gst_element_class_set_details (element_class, &gst_output_selector_details);
116
88
gst_element_class_add_pad_template (element_class,
126
98
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
128
100
parent_class = g_type_class_peek_parent (klass);
102
gobject_class->dispose = gst_output_selector_dispose;
129
104
gobject_class->set_property =
130
105
GST_DEBUG_FUNCPTR (gst_output_selector_set_property);
131
106
gobject_class->get_property =
132
107
GST_DEBUG_FUNCPTR (gst_output_selector_get_property);
133
109
g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD,
134
g_param_spec_string ("active-pad", "Active pad",
135
"Name of the currently active src pad", NULL, G_PARAM_READWRITE));
110
g_param_spec_object ("active-pad", "Active pad",
111
"Currently active src pad", GST_TYPE_PAD, G_PARAM_READWRITE));
136
112
g_object_class_install_property (gobject_class, PROP_RESEND_LATEST,
137
113
g_param_spec_boolean ("resend-latest", "Resend latest buffer",
138
114
"Resend latest buffer after a switch to a new pad", FALSE,
139
115
G_PARAM_READWRITE));
140
gobject_class->dispose = gst_output_selector_dispose;
141
117
gstelement_class->request_new_pad =
142
118
GST_DEBUG_FUNCPTR (gst_output_selector_request_new_pad);
143
119
gstelement_class->release_pad =
144
120
GST_DEBUG_FUNCPTR (gst_output_selector_release_pad);
145
122
gstelement_class->change_state = gst_output_selector_change_state;
124
GST_DEBUG_CATEGORY_INIT (output_selector_debug,
125
"output-selector", 0, "An output stream selector element");
150
gst_output_selector_init (GstOutputSelector * sel)
129
gst_output_selector_init (GstOutputSelector * sel,
130
GstOutputSelectorClass * g_class)
153
133
gst_pad_new_from_static_template (&gst_output_selector_sink_factory,
201
181
GstOutputSelector *sel = GST_OUTPUT_SELECTOR (object);
203
183
switch (prop_id) {
204
case PROP_ACTIVE_PAD:{
206
gst_element_get_static_pad (GST_ELEMENT (sel),
207
g_value_get_string (value));
209
GST_WARNING ("pad %s not found, activation failed",
210
g_value_get_string (value));
184
case PROP_ACTIVE_PAD:
188
next_pad = g_value_get_object (value);
190
GST_LOG_OBJECT (sel, "Activating pad %s:%s",
191
GST_DEBUG_PAD_NAME (next_pad));
193
GST_OBJECT_LOCK (object);
213
194
if (next_pad != sel->active_srcpad) {
214
195
/* switch to new srcpad in next chain run */
215
196
if (sel->pending_srcpad != NULL) {
216
197
GST_INFO ("replacing pending switch");
217
198
gst_object_unref (sel->pending_srcpad);
201
gst_object_ref (next_pad);
219
202
sel->pending_srcpad = next_pad;
221
204
GST_INFO ("pad already active");
222
gst_object_unref (next_pad);
205
if (sel->pending_srcpad != NULL) {
206
gst_object_unref (sel->pending_srcpad);
207
sel->pending_srcpad = NULL;
210
GST_OBJECT_UNLOCK (object);
226
213
case PROP_RESEND_LATEST:{
240
227
GstOutputSelector *sel = GST_OUTPUT_SELECTOR (object);
242
229
switch (prop_id) {
243
case PROP_ACTIVE_PAD:{
230
case PROP_ACTIVE_PAD:
244
231
GST_OBJECT_LOCK (object);
245
if (sel->active_srcpad != NULL) {
246
g_value_take_string (value, gst_pad_get_name (sel->active_srcpad));
248
g_value_set_string (value, "");
232
g_value_set_object (value, sel->active_srcpad);
250
233
GST_OBJECT_UNLOCK (object);
253
235
case PROP_RESEND_LATEST:{
254
236
GST_OBJECT_LOCK (object);
255
237
g_value_set_boolean (value, sel->resend_latest);
328
310
ev = gst_event_new_new_segment (TRUE, seg->rate,
329
311
seg->format, start, seg->stop, position);
330
312
if (!gst_pad_push_event (osel->pending_srcpad, ev)) {
331
GST_WARNING ("newsegment handling failed in %" GST_PTR_FORMAT,
313
GST_WARNING_OBJECT (osel,
314
"newsegment handling failed in %" GST_PTR_FORMAT,
332
315
osel->pending_srcpad);
343
326
osel->active_srcpad = osel->pending_srcpad;
345
GST_WARNING ("switch failed, pad not linked");
328
GST_WARNING_OBJECT (osel, "switch failed, pad not linked");
369
352
/* Keep reference to latest buffer to resend it after switch */
370
if (osel->resend_latest) {
371
if (osel->latest_buffer)
372
gst_buffer_unref (osel->latest_buffer);
373
osel->latest_buffer = gst_buffer_ref (buf);
353
if (osel->latest_buffer)
354
gst_buffer_unref (osel->latest_buffer);
355
osel->latest_buffer = gst_buffer_ref (buf);
376
357
/* Keep track of last stop and use it in NEWSEGMENT start after
377
358
switching to a new src pad */
381
362
if (GST_CLOCK_TIME_IS_VALID (duration)) {
382
363
last_stop += duration;
384
GST_LOG ("setting last stop %" GST_TIME_FORMAT, GST_TIME_ARGS (last_stop));
365
GST_LOG_OBJECT (osel, "setting last stop %" GST_TIME_FORMAT,
366
GST_TIME_ARGS (last_stop));
385
367
gst_segment_set_last_stop (&osel->segment, osel->segment.format, last_stop);
388
GST_LOG ("pushing buffer to %" GST_PTR_FORMAT, osel->active_srcpad);
370
GST_LOG_OBJECT (osel, "pushing buffer to %" GST_PTR_FORMAT,
371
osel->active_srcpad);
389
372
res = gst_pad_push (osel->active_srcpad, buf);
390
373
gst_object_unref (osel);
418
402
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
419
403
&start, &stop, &time);
421
GST_DEBUG ("configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
423
"%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
405
GST_DEBUG_OBJECT (sel,
406
"configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
407
"format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
424
408
G_GINT64_FORMAT, update, rate, arate, format, start, stop, time);
426
410
gst_segment_set_newsegment_full (&sel->segment, update,
436
420
gst_pad_event_default (pad, event);
439
/* Send other events to active src pad */
440
res = gst_pad_push_event (sel->active_srcpad, event);
423
/* Send other events to pending or active src pad */
425
sel->pending_srcpad ? sel->pending_srcpad : sel->active_srcpad;
426
res = gst_pad_push_event (output_pad, event);