diff --git a/gst/encoding/Makefile.am b/gst/encoding/Makefile.am index 85efbd144c..8ce1978276 100644 --- a/gst/encoding/Makefile.am +++ b/gst/encoding/Makefile.am @@ -17,7 +17,8 @@ noinst_HEADERS = \ gstencodebin.h \ gststreamcombiner.h \ gststreamsplitter.h \ - gstsmartencoder.h + gstsmartencoder.h \ + gststreamcombinerpad.h include $(top_srcdir)/common/gst-glib-gen.mak diff --git a/gst/encoding/gststreamcombiner.c b/gst/encoding/gststreamcombiner.c index 2eb73c2feb..518b377435 100644 --- a/gst/encoding/gststreamcombiner.c +++ b/gst/encoding/gststreamcombiner.c @@ -23,6 +23,7 @@ #endif #include "gststreamcombiner.h" +#include "gststreamcombinerpad.h" static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, @@ -38,6 +39,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_stream_combiner_debug); G_DEFINE_TYPE (GstStreamCombiner, gst_stream_combiner, GST_TYPE_ELEMENT); +G_DEFINE_TYPE (GstStreamCombinerPad, gst_stream_combiner_pad, GST_TYPE_PAD); + #define STREAMS_LOCK(obj) (g_mutex_lock(&obj->lock)) #define STREAMS_UNLOCK(obj) (g_mutex_unlock(&obj->lock)) @@ -48,6 +51,18 @@ static GstPad *gst_stream_combiner_request_new_pad (GstElement * element, static void gst_stream_combiner_release_pad (GstElement * element, GstPad * pad); +static void +gst_stream_combiner_pad_class_init (GstStreamCombinerPadClass * klass) +{ + return; +} + +static void +gst_stream_combiner_pad_init (GstStreamCombinerPad * mixerpad) +{ + mixerpad->is_eos = FALSE; +} + static void gst_stream_combiner_class_init (GstStreamCombinerClass * klass) { @@ -98,33 +113,54 @@ gst_stream_combiner_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) return gst_pad_push (stream_combiner->srcpad, buf); } +static gboolean +_all_sink_pads_eos (GstStreamCombiner * combiner) +{ + GList *tmp; + + for (tmp = combiner->sinkpads; tmp; tmp = tmp->next) { + if (!(GST_STREAM_COMBINER_PAD (tmp->data))->is_eos) + return FALSE; + } + + return TRUE; +} + static gboolean gst_stream_combiner_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstStreamCombiner *stream_combiner = (GstStreamCombiner *) parent; + GstStreamCombinerPad *combiner_pad = GST_STREAM_COMBINER_PAD (pad); /* FIXME : IMPLEMENT */ GST_DEBUG_OBJECT (pad, "Got event %s", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CUSTOM_DOWNSTREAM: - if (gst_event_has_name (event, "stream-switching-eos")) { + case GST_EVENT_EOS: + GST_PAD_STREAM_LOCK (pad); + + combiner_pad->is_eos = TRUE; + if (!_all_sink_pads_eos (stream_combiner)) { gst_event_unref (event); - event = gst_event_new_eos (); + event = NULL; + } else { + GST_DEBUG_OBJECT (stream_combiner, "All sink pads eos, pushing eos"); } + + GST_PAD_STREAM_UNLOCK (pad); break; default: break; } /* SEGMENT : lock, wait for other stream to EOS, select stream, unlock, push */ - /* EOS : lock, mark pad as unused, unlock , drop event */ - /* CUSTOM_REAL_EOS : push EOS downstream */ /* FLUSH_START : lock, mark as flushing, unlock. if wasn't flushing forward */ /* FLUSH_STOP : lock, unmark as flushing, unlock, if was flushing forward */ /* OTHER : if selected pad forward */ - return gst_pad_push_event (stream_combiner->srcpad, event); + if (event) + return gst_pad_push_event (stream_combiner->srcpad, event); + return FALSE; } static gboolean @@ -204,11 +240,18 @@ gst_stream_combiner_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps) { GstStreamCombiner *stream_combiner = (GstStreamCombiner *) element; + GstStreamCombinerPad *combiner_pad; GstPad *sinkpad; + GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); + GstPadTemplate *template = + gst_element_class_get_pad_template (klass, "sink_%u"); GST_DEBUG_OBJECT (element, "templ:%p, name:%s", templ, name); - sinkpad = gst_pad_new_from_static_template (&sink_template, name); + combiner_pad = g_object_new (GST_TYPE_STREAM_COMBINER_PAD, "name", name, + "template", template, "direction", template->direction, NULL); + + sinkpad = GST_PAD_CAST (combiner_pad); gst_pad_set_chain_function (sinkpad, gst_stream_combiner_chain); gst_pad_set_event_function (sinkpad, gst_stream_combiner_sink_event); gst_pad_set_query_function (sinkpad, gst_stream_combiner_sink_query); diff --git a/gst/encoding/gststreamcombinerpad.h b/gst/encoding/gststreamcombinerpad.h new file mode 100644 index 0000000000..a72ff60663 --- /dev/null +++ b/gst/encoding/gststreamcombinerpad.h @@ -0,0 +1,63 @@ +/* Streamcombiner special-purpose pad + * Copyright (C) 2013 MathieuDuponchelle + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_STREAM_COMBINER_PAD_H__ +#define __GST_STREAM_COMBINER_PAD_H__ + +#include +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STREAM_COMBINER_PAD (gst_stream_combiner_pad_get_type()) +#define GST_STREAM_COMBINER_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_STREAM_COMBINER_PAD, GstStreamCombinerPad)) +#define GST_STREAM_COMBINER_PAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_MIXER_PAD, GstStreamCombinerPadClass)) +#define GST_IS_STREAM_COMBINER_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_STREAM_COMBINER_PAD)) +#define GST_IS_STREAM_COMBINER_PAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_STREAM_COMBINER_PAD)) + +typedef struct _GstStreamCombinerPad GstStreamCombinerPad; +typedef struct _GstStreamCombinerPadClass GstStreamCombinerPadClass; + +/** + * GstStream_CombinerPad: + * + * The opaque #GstStreamCombinerPad structure. + */ +struct _GstStreamCombinerPad +{ + GstPad parent; + + gboolean is_eos; +}; + +struct _GstStreamCombinerPadClass +{ + GstPadClass parent_class; +}; + +GType gst_stream_combiner_pad_get_type (void); + +G_END_DECLS +#endif /* __GST_STREAM_COMBINER_PAD_H__ */ diff --git a/gst/encoding/gststreamsplitter.c b/gst/encoding/gststreamsplitter.c index ad8b161b26..114d38b6ec 100644 --- a/gst/encoding/gststreamsplitter.c +++ b/gst/encoding/gststreamsplitter.c @@ -151,11 +151,9 @@ gst_stream_splitter_sink_event (GstPad * pad, GstObject * parent, gboolean res = TRUE; gboolean toall = FALSE; gboolean store = FALSE; - gboolean eos = FALSE; gboolean flushpending = FALSE; /* FLUSH_START/STOP : forward to all - * EOS : transform to CUSTOM_REAL_EOS and forward to all * INBAND events : store to send in chain function to selected chain * OUT_OF_BAND events : send to all */ @@ -182,13 +180,7 @@ gst_stream_splitter_sink_event (GstPad * pad, GstObject * parent, toall = TRUE; break; case GST_EVENT_EOS: - /* Replace with our custom eos event */ - gst_event_unref (event); - event = - gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, - gst_structure_new_empty ("stream-switching-eos")); toall = TRUE; - eos = TRUE; break; default: if (GST_EVENT_TYPE (event) & GST_EVENT_TYPE_SERIALIZED) @@ -205,7 +197,7 @@ gst_stream_splitter_sink_event (GstPad * pad, GstObject * parent, if (store) { stream_splitter->pending_events = g_list_append (stream_splitter->pending_events, event); - } else if (toall || eos) { + } else if (toall) { GList *tmp; guint32 cookie; @@ -224,12 +216,6 @@ gst_stream_splitter_sink_event (GstPad * pad, GstObject * parent, while (tmp) { GstPad *srcpad = (GstPad *) tmp->data; STREAMS_UNLOCK (stream_splitter); - /* In case of EOS, we first push out the real one to flush out - * each streams (but which will be discarded in the streamcombiner) - * before our custom one (which will be converted back to and EOS - * in the streamcombiner) */ - if (eos) - gst_pad_push_event (srcpad, gst_event_new_eos ()); gst_event_ref (event); res = gst_pad_push_event (srcpad, event); STREAMS_LOCK (stream_splitter);