mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
first phase of spider cleanup
Original commit message from CVS: first phase of spider cleanup - get rid of the buffer cache for type finding - do type finding within spider identity instead of in seperate element - currently doing type finding with the first buffer only. will eventually merge buffer until there is "enough" data to typefind with - spider now only has 1 sink instead of many. I don't believe it would be possible to mux with spider anyway - if type finding fails, gst_element_error is called. Its up to the app to catch the error signal and stop the pipeline
This commit is contained in:
parent
ee02fdd30e
commit
7fec8602c3
4 changed files with 146 additions and 206 deletions
|
@ -65,15 +65,6 @@ GST_PAD_TEMPLATE_FACTORY (spider_src_factory,
|
|||
NULL /* no caps */
|
||||
);
|
||||
|
||||
GST_PAD_TEMPLATE_FACTORY (spider_sink_factory,
|
||||
"sink_%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
NULL /* no caps */
|
||||
);
|
||||
|
||||
|
||||
|
||||
/* standard GObject stuff */
|
||||
static void gst_spider_class_init (GstSpiderClass *klass);
|
||||
static void gst_spider_init (GstSpider *spider);
|
||||
|
@ -85,12 +76,12 @@ static void gst_spider_set_property (GObject *object, guint pr
|
|||
static void gst_spider_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
|
||||
/* connection functions */
|
||||
static GstSpiderConnection * gst_spider_connection_new (GstSpiderIdentity *sink, GstSpiderIdentity *src);
|
||||
static GstSpiderConnection * gst_spider_connection_new (GstSpiderIdentity *src);
|
||||
static void gst_spider_connection_destroy (GstSpiderConnection *conn);
|
||||
static void gst_spider_connection_reset (GstSpiderConnection *conn, GstElement *to);
|
||||
static void gst_spider_connection_add (GstSpiderConnection *conn, GstElement *element);
|
||||
static GstSpiderConnection * gst_spider_connection_find (GstSpiderIdentity *sink, GstSpiderIdentity *src);
|
||||
static GstSpiderConnection * gst_spider_connection_get (GstSpiderIdentity *sink, GstSpiderIdentity *src);
|
||||
static GstSpiderConnection * gst_spider_connection_find (GstSpiderIdentity *src);
|
||||
static GstSpiderConnection * gst_spider_connection_get (GstSpiderIdentity *src);
|
||||
|
||||
/* autoplugging functions */
|
||||
static GstElement * gst_spider_find_element_to_plug (GstElement *src, GstElementFactory *fac, GstPadDirection dir);
|
||||
|
@ -113,12 +104,6 @@ static GstElementClass * parent_class = NULL;
|
|||
static guint gst_spider_signals[LAST_SIGNAL] = { 0 };*/
|
||||
|
||||
/* let gstreamer know that we have some request pads available */
|
||||
GST_PAD_TEMPLATE_FACTORY (gst_spider_sink_template_factory,
|
||||
"sink%d",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
NULL
|
||||
);
|
||||
GST_PAD_TEMPLATE_FACTORY (gst_spider_src_template_factory,
|
||||
"src%d",
|
||||
GST_PAD_SRC,
|
||||
|
@ -169,7 +154,6 @@ gst_spider_class_init (GstSpiderClass *klass)
|
|||
gobject_class->dispose = gst_spider_dispose;
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class, gst_spider_src_template_factory());
|
||||
gst_element_class_add_pad_template (gstelement_class, gst_spider_sink_template_factory());
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_spider_request_new_pad);
|
||||
}
|
||||
|
@ -182,6 +166,11 @@ gst_spider_init (GstSpider *spider)
|
|||
gst_registry_pool_feature_list (GST_TYPE_ELEMENT_FACTORY));
|
||||
|
||||
spider->connections = NULL;
|
||||
|
||||
spider->sink_ident = gst_spider_identity_new_sink ("sink_ident");
|
||||
gst_bin_add (GST_BIN (spider), GST_ELEMENT (spider->sink_ident));
|
||||
gst_element_add_ghost_pad (GST_ELEMENT(spider), spider->sink_ident->sink, "sink");
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -204,27 +193,14 @@ gst_spider_request_new_pad (GstElement *element, GstPadTemplate *templ, const gc
|
|||
|
||||
g_return_val_if_fail (templ != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
|
||||
g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC, NULL);
|
||||
|
||||
spider = GST_SPIDER (element);
|
||||
|
||||
/* create an identity object, so we have a pad */
|
||||
switch ( GST_PAD_TEMPLATE_DIRECTION (templ))
|
||||
{
|
||||
case GST_PAD_SRC:
|
||||
padname = gst_spider_unused_elementname ((GstBin *)spider, "src_");
|
||||
identity = gst_spider_identity_new_src (padname);
|
||||
returnpad = identity->src;
|
||||
break;
|
||||
case GST_PAD_SINK:
|
||||
padname = gst_spider_unused_elementname ((GstBin *)spider, "sink_");
|
||||
identity = gst_spider_identity_new_sink (padname);
|
||||
returnpad = identity->sink;
|
||||
break;
|
||||
case GST_PAD_UNKNOWN:
|
||||
default:
|
||||
g_warning("Spider: you must request a source or sink pad.");
|
||||
return NULL;
|
||||
}
|
||||
padname = gst_spider_unused_elementname ((GstBin *)spider, "src_");
|
||||
identity = gst_spider_identity_new_src (padname);
|
||||
returnpad = identity->src;
|
||||
|
||||
/* FIXME: use the requested name for the pad */
|
||||
|
||||
|
@ -234,6 +210,7 @@ gst_spider_request_new_pad (GstElement *element, GstPadTemplate *templ, const gc
|
|||
gst_bin_add (GST_BIN (element), GST_ELEMENT (identity));
|
||||
|
||||
returnpad = gst_element_add_ghost_pad (element, returnpad, padname);
|
||||
gst_spider_connection_new (identity);
|
||||
GST_DEBUG (GST_CAT_ELEMENT_PADS, "successuflly created requested pad %s:%s", GST_DEBUG_PAD_NAME (returnpad));
|
||||
|
||||
return returnpad;
|
||||
|
@ -304,7 +281,7 @@ gst_spider_connect_sometimes (GstElement *src, GstPad *pad, GstSpiderConnection
|
|||
gboolean restart = FALSE;
|
||||
gulong signal_id = conn->signal_id;
|
||||
GstPad *sinkpad = conn->src->sink;
|
||||
GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (conn->sink));
|
||||
GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (conn->src));
|
||||
|
||||
/* check if restarting is necessary */
|
||||
if (gst_element_get_state ((GstElement *) spider) == GST_STATE_PLAYING)
|
||||
|
@ -328,16 +305,15 @@ gst_spider_connect_sometimes (GstElement *src, GstPad *pad, GstSpiderConnection
|
|||
}
|
||||
/* create a new connection from those two elements */
|
||||
static GstSpiderConnection *
|
||||
gst_spider_connection_new (GstSpiderIdentity *sink, GstSpiderIdentity *src)
|
||||
gst_spider_connection_new (GstSpiderIdentity *src)
|
||||
{
|
||||
GstSpider *spider;
|
||||
GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (src));
|
||||
|
||||
GstSpiderConnection *conn = g_new0 (GstSpiderConnection, 1);
|
||||
conn->src = src;
|
||||
conn->sink = sink;
|
||||
conn->current = (GstElement *) sink;
|
||||
conn->path = NULL;
|
||||
spider = GST_SPIDER (GST_OBJECT_PARENT (src));
|
||||
conn->current = (GstElement *) spider->sink_ident;
|
||||
g_print("creating new connection\n");
|
||||
spider->connections = g_list_prepend (spider->connections, conn);
|
||||
|
||||
return conn;
|
||||
|
@ -345,14 +321,16 @@ gst_spider_connection_new (GstSpiderIdentity *sink, GstSpiderIdentity *src)
|
|||
static void
|
||||
gst_spider_connection_destroy (GstSpiderConnection *conn)
|
||||
{
|
||||
GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (conn->src));
|
||||
/* reset connection to unplugged */
|
||||
gst_spider_connection_reset (conn, (GstElement *) conn->sink);
|
||||
gst_spider_connection_reset (conn, (GstElement *) spider->sink_ident);
|
||||
g_free (conn);
|
||||
}
|
||||
static void
|
||||
gst_spider_connection_reset (GstSpiderConnection *conn, GstElement *to)
|
||||
{
|
||||
GST_DEBUG (GST_CAT_AUTOPLUG, "resetting connection from %s to %s, currently at %s to %s", GST_ELEMENT_NAME (conn->sink),
|
||||
GstSpider *spider = GST_SPIDER (GST_OBJECT_PARENT (conn->src));
|
||||
GST_DEBUG (GST_CAT_AUTOPLUG, "resetting connection from %s to %s, currently at %s to %s", GST_ELEMENT_NAME (spider->sink_ident),
|
||||
GST_ELEMENT_NAME (conn->src), GST_ELEMENT_NAME (conn->current), GST_ELEMENT_NAME (to));
|
||||
while ((conn->path != NULL) && ((GstElement *) conn->path->data != to))
|
||||
{
|
||||
|
@ -361,7 +339,7 @@ gst_spider_connection_reset (GstSpiderConnection *conn, GstElement *to)
|
|||
}
|
||||
if (conn->path == NULL)
|
||||
{
|
||||
conn->current = (GstElement *) conn->sink;
|
||||
conn->current = (GstElement *) spider->sink_ident;
|
||||
} else {
|
||||
conn->current = to;
|
||||
}
|
||||
|
@ -377,18 +355,17 @@ gst_spider_connection_add (GstSpiderConnection *conn, GstElement *element)
|
|||
}
|
||||
/* find the connection from those two elements */
|
||||
static GstSpiderConnection *
|
||||
gst_spider_connection_find (GstSpiderIdentity *sink, GstSpiderIdentity *src)
|
||||
gst_spider_connection_find (GstSpiderIdentity *src)
|
||||
{
|
||||
GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (src);
|
||||
GList *list = spider->connections;
|
||||
|
||||
g_assert (spider == (GstSpider *) GST_OBJECT_PARENT (sink));
|
||||
|
||||
while (list)
|
||||
{
|
||||
GstSpiderConnection *conn = (GstSpiderConnection *) list->data;
|
||||
if (conn->src == src && conn->sink == sink)
|
||||
if (conn->src == src){
|
||||
return conn;
|
||||
}
|
||||
list = g_list_next(list);
|
||||
}
|
||||
return NULL;
|
||||
|
@ -396,15 +373,15 @@ gst_spider_connection_find (GstSpiderIdentity *sink, GstSpiderIdentity *src)
|
|||
/* get a new connection from those two elements
|
||||
* search first; if none is found, create a new one */
|
||||
static GstSpiderConnection *
|
||||
gst_spider_connection_get (GstSpiderIdentity *sink, GstSpiderIdentity *src)
|
||||
gst_spider_connection_get (GstSpiderIdentity *src)
|
||||
{
|
||||
GstSpiderConnection *ret;
|
||||
|
||||
if ((ret = gst_spider_connection_find (sink, src)) != NULL)
|
||||
if ((ret = gst_spider_connection_find (src)) != NULL)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
return gst_spider_connection_new (sink, src);
|
||||
return gst_spider_connection_new (src);
|
||||
}
|
||||
void
|
||||
gst_spider_identity_plug (GstSpiderIdentity *ident)
|
||||
|
@ -465,11 +442,11 @@ gst_spider_identity_plug (GstSpiderIdentity *ident)
|
|||
/* plug in the right direction */
|
||||
if (dir == GST_PAD_SINK)
|
||||
{
|
||||
conn = gst_spider_connection_get (ident, peer);
|
||||
conn = gst_spider_connection_get (peer);
|
||||
} else {
|
||||
conn = gst_spider_connection_get (peer, ident);
|
||||
conn = gst_spider_connection_get (ident);
|
||||
}
|
||||
if ((GstElement *) conn->sink == conn->current)
|
||||
if ((GstElement *) spider->sink_ident == conn->current)
|
||||
{
|
||||
gboolean restart = FALSE;
|
||||
/* check if restarting is necessary */
|
||||
|
@ -503,7 +480,7 @@ gst_spider_identity_unplug (GstSpiderIdentity *ident)
|
|||
GstSpiderConnection *conn = list->data;
|
||||
GList *cur = list;
|
||||
list = g_list_next (list);
|
||||
if ((conn->src == ident) || (conn->sink == ident))
|
||||
if (conn->src == ident)
|
||||
{
|
||||
g_list_delete_link (spider->connections, cur);
|
||||
gst_spider_connection_destroy (conn);
|
||||
|
@ -516,7 +493,7 @@ gst_spider_identity_unplug (GstSpiderIdentity *ident)
|
|||
static GstPadConnectReturn
|
||||
gst_spider_create_and_plug (GstSpiderConnection *conn, GList *plugpath)
|
||||
{
|
||||
GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (conn->sink);
|
||||
GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (conn->src);
|
||||
GList *endelements = NULL, *templist = NULL;
|
||||
GstElement *element;
|
||||
|
||||
|
@ -617,10 +594,11 @@ gst_spider_find_element_to_plug (GstElement *src, GstElementFactory *fac, GstPad
|
|||
static GstPadConnectReturn
|
||||
gst_spider_plug (GstSpiderConnection *conn)
|
||||
{
|
||||
GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (conn->src);
|
||||
if ((GstElement *) conn->src == conn->current)
|
||||
return GST_PAD_CONNECT_DONE;
|
||||
if ((GstElement *) conn->sink == conn->current)
|
||||
return gst_spider_plug_from_srcpad (conn, conn->sink->src);
|
||||
if ((GstElement *) spider->sink_ident == conn->current)
|
||||
return gst_spider_plug_from_srcpad (conn, spider->sink_ident->src);
|
||||
g_warning ("FIXME: autoplugging only possible from GstSpiderIdentity conn->sink yet (yep, that's technical)\n");
|
||||
return GST_PAD_CONNECT_REFUSED;
|
||||
}
|
||||
|
@ -640,10 +618,10 @@ gst_spider_plug_from_srcpad (GstSpiderConnection *conn, GstPad *srcpad)
|
|||
|
||||
/* find a path from src to sink */
|
||||
/* FIXME: make that if go away and work anyway */
|
||||
if (srcpad == conn->sink->src)
|
||||
if (srcpad == spider->sink_ident->src)
|
||||
{
|
||||
g_assert (GST_RPAD_PEER (conn->sink->sink) != NULL);
|
||||
plugpath = gst_autoplug_sp (gst_pad_get_caps ((GstPad *) GST_RPAD_PEER (conn->sink->sink)), gst_pad_get_caps (conn->src->sink), spider->factories);
|
||||
g_assert (GST_RPAD_PEER (spider->sink_ident->sink) != NULL);
|
||||
plugpath = gst_autoplug_sp (gst_pad_get_caps ((GstPad *) GST_RPAD_PEER (spider->sink_ident->sink)), gst_pad_get_caps (conn->src->sink), spider->factories);
|
||||
} else {
|
||||
plugpath = gst_autoplug_sp (gst_pad_get_caps (srcpad), gst_pad_get_caps (conn->src->sink), spider->factories);
|
||||
}
|
||||
|
@ -709,7 +687,6 @@ plugin_init (GModule *module, GstPlugin *plugin)
|
|||
g_return_val_if_fail(factory != NULL, FALSE);
|
||||
|
||||
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (spider_src_factory));
|
||||
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (spider_sink_factory));
|
||||
|
||||
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ extern GstElementDetails gst_spider_details;
|
|||
* A GstSpider keeps a list of all GstSpiderConnections in it.
|
||||
*/
|
||||
typedef struct {
|
||||
GstSpiderIdentity *sink;
|
||||
GstSpiderIdentity *src;
|
||||
/* dunno if the path should stay here or if its too much load.
|
||||
* it's at least easier then always searching it */
|
||||
|
@ -72,6 +71,7 @@ typedef struct _GstSpiderClass GstSpiderClass;
|
|||
struct _GstSpider {
|
||||
GstBin parent;
|
||||
|
||||
GstSpiderIdentity *sink_ident;
|
||||
GList * factories; /* factories to use for plugging */
|
||||
|
||||
GList * connections; /* GStSpiderConnection list of all connections */
|
||||
|
|
|
@ -77,16 +77,9 @@ static GstCaps * gst_spider_identity_getcaps (GstPad *pad, GstCaps *caps);
|
|||
static void gst_spider_identity_dumb_loop (GstSpiderIdentity *ident);
|
||||
static void gst_spider_identity_src_loop (GstSpiderIdentity *ident);
|
||||
static void gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident);
|
||||
static void gst_spider_identity_sink_loop_emptycache (GstSpiderIdentity *ident);
|
||||
|
||||
static gboolean gst_spider_identity_handle_src_event (GstPad *pad, GstEvent *event);
|
||||
|
||||
/* set/get functions */
|
||||
static void gst_spider_identity_set_caps (GstSpiderIdentity *identity, GstCaps *caps);
|
||||
|
||||
/* callback */
|
||||
static void callback_type_find_have_type (GstElement *typefind, GstCaps *caps, GstSpiderIdentity *identity);
|
||||
|
||||
/* other functions */
|
||||
static void gst_spider_identity_start_type_finding (GstSpiderIdentity *ident);
|
||||
|
||||
|
@ -159,10 +152,6 @@ gst_spider_identity_init (GstSpiderIdentity *ident)
|
|||
/* variables */
|
||||
ident->plugged = FALSE;
|
||||
|
||||
/* caching */
|
||||
ident->cache_start = NULL;
|
||||
ident->cache_end = NULL;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -170,7 +159,7 @@ gst_spider_identity_chain (GstPad *pad, GstBuffer *buf)
|
|||
{
|
||||
GstSpiderIdentity *ident;
|
||||
|
||||
/* g_print ("chaining on pad %s:%s with buffer %p\n", GST_DEBUG_PAD_NAME (pad), buf); */
|
||||
/*g_print ("chaining on pad %s:%s with buffer %p\n", GST_DEBUG_PAD_NAME (pad), buf);*/
|
||||
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
|
@ -185,15 +174,14 @@ gst_spider_identity_chain (GstPad *pad, GstBuffer *buf)
|
|||
{
|
||||
GstSpider *spider = (GstSpider *) GST_OBJECT_PARENT (ident);
|
||||
GList *list = spider->connections;
|
||||
g_print("have EOS in chain\n");
|
||||
while (list)
|
||||
{
|
||||
GstSpiderConnection *conn = (GstSpiderConnection *) list->data;
|
||||
list = g_list_next (list);
|
||||
if (conn->sink == ident)
|
||||
{
|
||||
gst_element_set_eos (GST_ELEMENT (conn->src));
|
||||
gst_pad_push (conn->src->src, GST_BUFFER (gst_event_new (GST_EVENT_EOS)));
|
||||
}
|
||||
g_print("forwarding EOS to conn\n");
|
||||
gst_element_set_eos (GST_ELEMENT (conn->src));
|
||||
gst_pad_push (conn->src->src, GST_BUFFER (gst_event_new (GST_EVENT_EOS)));
|
||||
}
|
||||
}
|
||||
/* end hack for current event stuff here */
|
||||
|
@ -363,8 +351,8 @@ gst_spider_identity_change_state (GstElement *element)
|
|||
static void
|
||||
gst_spider_identity_start_type_finding (GstSpiderIdentity *ident)
|
||||
{
|
||||
GstElement* typefind;
|
||||
gchar *name;
|
||||
/* GstElement* typefind;
|
||||
gchar *name;*/
|
||||
gboolean restart = FALSE;
|
||||
|
||||
GST_DEBUG (GST_CAT_AUTOPLUG, "element %s starts typefinding", GST_ELEMENT_NAME(ident));
|
||||
|
@ -373,17 +361,7 @@ gst_spider_identity_start_type_finding (GstSpiderIdentity *ident)
|
|||
gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT (ident)), GST_STATE_PAUSED);
|
||||
restart = TRUE;
|
||||
}
|
||||
|
||||
/* create and connect typefind object */
|
||||
name = g_strdup_printf ("%s%s", "typefind", GST_ELEMENT_NAME(ident));
|
||||
typefind = gst_element_factory_make ("typefind", name);
|
||||
g_free (name);
|
||||
|
||||
g_signal_connect (G_OBJECT (typefind), "have_type",
|
||||
G_CALLBACK (callback_type_find_have_type), ident);
|
||||
gst_bin_add (GST_BIN (GST_ELEMENT_PARENT (ident)), typefind);
|
||||
gst_pad_connect (gst_element_get_compatible_pad ((GstElement *) ident, gst_element_get_pad (typefind, "sink")), gst_element_get_pad (typefind, "sink"));
|
||||
|
||||
|
||||
gst_element_set_loop_function (GST_ELEMENT (ident), (GstElementLoopFunction) GST_DEBUG_FUNCPTR (gst_spider_identity_sink_loop_type_finding));
|
||||
|
||||
if (restart)
|
||||
|
@ -391,58 +369,7 @@ gst_spider_identity_start_type_finding (GstSpiderIdentity *ident)
|
|||
gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT (ident)), GST_STATE_PLAYING);
|
||||
}
|
||||
}
|
||||
/* waiting for a good suggestion on where to set the caps from typefinding
|
||||
* Caps must be cleared when pad is disconnected
|
||||
*
|
||||
* Currently we are naive and set the caps on the source of the identity object
|
||||
* directly and hope to avoid any disturbance in the force.
|
||||
*/
|
||||
void
|
||||
gst_spider_identity_set_caps (GstSpiderIdentity *ident, GstCaps *caps)
|
||||
{
|
||||
if (ident->src)
|
||||
{
|
||||
gst_pad_try_set_caps (ident->src, caps);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
callback_type_find_have_type (GstElement *typefind, GstCaps *caps, GstSpiderIdentity *ident)
|
||||
{
|
||||
gboolean restart_spider = FALSE;
|
||||
|
||||
GST_INFO (GST_CAT_AUTOPLUG, "element %s has found caps\n", GST_ELEMENT_NAME(ident));
|
||||
|
||||
/* checks */
|
||||
g_assert (GST_IS_ELEMENT (typefind));
|
||||
g_assert (GST_IS_SPIDER_IDENTITY (ident));
|
||||
|
||||
/* pause the autoplugger */
|
||||
if (gst_element_get_state (GST_ELEMENT (GST_ELEMENT_PARENT(ident))) == GST_STATE_PLAYING)
|
||||
{
|
||||
gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT(ident)), GST_STATE_PAUSED);
|
||||
restart_spider = TRUE;
|
||||
}
|
||||
|
||||
/* remove typefind */
|
||||
gst_pad_disconnect (ident->src, (GstPad*) GST_RPAD_PEER (ident->src));
|
||||
gst_bin_remove (GST_BIN (GST_ELEMENT_PARENT (ident)), typefind);
|
||||
|
||||
/* set caps */
|
||||
gst_spider_identity_set_caps (ident, caps);
|
||||
|
||||
/* set new loop function, we gotta empty the cache */
|
||||
gst_element_set_loop_function (GST_ELEMENT (ident), (GstElementLoopFunction) GST_DEBUG_FUNCPTR (gst_spider_identity_sink_loop_emptycache));
|
||||
|
||||
/* autoplug this pad */
|
||||
gst_spider_identity_plug (ident);
|
||||
|
||||
/* restart autoplugger */
|
||||
if (restart_spider)
|
||||
gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT(ident)), GST_STATE_PLAYING);
|
||||
|
||||
}
|
||||
/* since we can't set the loop function to NULL if there's a cothread for us,
|
||||
* we have to use a dumb one
|
||||
*/
|
||||
|
@ -484,70 +411,119 @@ gst_spider_identity_src_loop (GstSpiderIdentity *ident)
|
|||
return;
|
||||
}
|
||||
/* This loop function is only needed when typefinding.
|
||||
* It works quite simple: get a new buffer, append it to the cache
|
||||
* and push it to the typefinder.
|
||||
*/
|
||||
static void
|
||||
gst_spider_identity_sink_loop_type_finding (GstSpiderIdentity *ident)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
GstBuffer *typefindbuf = NULL;
|
||||
gboolean getmorebuf = TRUE;
|
||||
GList *type_list;
|
||||
gboolean restart_spider = FALSE;
|
||||
|
||||
/* this should possibly be a property */
|
||||
guint bufsizelimit = 4096;
|
||||
|
||||
/* checks - disable for speed */
|
||||
g_return_if_fail (ident != NULL);
|
||||
g_return_if_fail (GST_IS_SPIDER_IDENTITY (ident));
|
||||
g_assert (ident->sink != NULL);
|
||||
|
||||
/* get buffer */
|
||||
buf = gst_pad_pull (ident->sink);
|
||||
|
||||
/* if it's an event... */
|
||||
while (GST_IS_EVENT (buf)) {
|
||||
/* handle DISCONT events, please */
|
||||
gst_pad_event_default (ident->sink, GST_EVENT (buf));
|
||||
buf = gst_pad_pull (ident->sink);
|
||||
}
|
||||
while (getmorebuf){
|
||||
|
||||
/* add it to the end of the cache */
|
||||
gst_buffer_ref (buf);
|
||||
GST_DEBUG (0, "element %s adds buffer %p (size %d) to cache", GST_ELEMENT_NAME(ident), buf, GST_BUFFER_SIZE (buf));
|
||||
ident->cache_end = g_list_prepend (ident->cache_end, buf);
|
||||
if (ident->cache_start == NULL)
|
||||
ident->cache_start = ident->cache_end;
|
||||
/* check if our buffer is big enough to do a typefind */
|
||||
if (typefindbuf && GST_BUFFER_SIZE(typefindbuf) >= bufsizelimit){
|
||||
getmorebuf = FALSE;
|
||||
break;
|
||||
}
|
||||
buf = gst_pad_pull (ident->sink);
|
||||
|
||||
/* if it's an event... */
|
||||
while (GST_IS_EVENT (buf)) {
|
||||
switch (GST_EVENT_TYPE (GST_EVENT (buf))){
|
||||
case GST_EVENT_EOS:
|
||||
getmorebuf = FALSE;
|
||||
g_print("have EOS\n");
|
||||
/* FIXME Notify the srcs that EOS has happened */
|
||||
gst_pad_event_default (ident->sink, GST_EVENT (buf));
|
||||
break;
|
||||
default:
|
||||
gst_pad_event_default (ident->sink, GST_EVENT (buf));
|
||||
buf = gst_pad_pull (ident->sink);
|
||||
break;
|
||||
}
|
||||
/* handle DISCONT events, please */
|
||||
}
|
||||
|
||||
typefindbuf = buf;
|
||||
getmorebuf = FALSE;
|
||||
/* FIXME merging doesn't work for some reason so
|
||||
* we'll just typefind with the first element
|
||||
if (!typefindbuf){
|
||||
typefindbuf = buf;
|
||||
gst_buffer_ref(buf);
|
||||
}
|
||||
else {
|
||||
GstBuffer *oldbuf = typefindbuf;
|
||||
typefindbuf = gst_buffer_merge(typefindbuf, buf);
|
||||
gst_buffer_unref(oldbuf);
|
||||
gst_buffer_unref(buf);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (!typefindbuf){
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* now do the actual typefinding with the supplied buffer */
|
||||
type_list = (GList *) gst_type_get_list ();
|
||||
|
||||
while (type_list) {
|
||||
GstType *type = (GstType *) type_list->data;
|
||||
GSList *factories = type->factories;
|
||||
|
||||
while (factories) {
|
||||
GstTypeFactory *factory = GST_TYPE_FACTORY (factories->data);
|
||||
GstTypeFindFunc typefindfunc = (GstTypeFindFunc)factory->typefindfunc;
|
||||
GstCaps *caps;
|
||||
|
||||
if (typefindfunc && (caps = typefindfunc (buf, factory))) {
|
||||
|
||||
/* pause the autoplugger */
|
||||
if (gst_element_get_state (GST_ELEMENT (GST_ELEMENT_PARENT(ident))) == GST_STATE_PLAYING) {
|
||||
gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT(ident)), GST_STATE_PAUSED);
|
||||
restart_spider = TRUE;
|
||||
}
|
||||
if (gst_pad_try_set_caps (ident->sink, caps) <= 0) {
|
||||
g_warning ("typefind: found type but peer didn't accept it");
|
||||
}
|
||||
gst_spider_identity_plug (ident);
|
||||
|
||||
/* restart autoplugger */
|
||||
if (restart_spider){
|
||||
gst_element_set_state (GST_ELEMENT (GST_ELEMENT_PARENT(ident)), GST_STATE_PLAYING);
|
||||
}
|
||||
|
||||
goto end;
|
||||
}
|
||||
factories = g_slist_next (factories);
|
||||
}
|
||||
type_list = g_list_next (type_list);
|
||||
}
|
||||
gst_element_error(GST_ELEMENT(ident), "Could not find media type", NULL);
|
||||
gst_buffer_unref(buf);
|
||||
buf = GST_BUFFER (gst_event_new (GST_EVENT_EOS));
|
||||
|
||||
end:
|
||||
|
||||
/* remove loop function */
|
||||
gst_element_set_loop_function (GST_ELEMENT (ident),
|
||||
(GstElementLoopFunction) GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
|
||||
|
||||
/* push the buffer */
|
||||
gst_spider_identity_chain (ident->sink, buf);
|
||||
}
|
||||
|
||||
/* this function is needed after typefinding:
|
||||
* empty the cache and when the cache is empty - remove this function
|
||||
*/
|
||||
static void
|
||||
gst_spider_identity_sink_loop_emptycache (GstSpiderIdentity *ident)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
|
||||
/* get the buffer and push it */
|
||||
buf = GST_BUFFER (ident->cache_start->data);
|
||||
gst_spider_identity_chain (ident->sink, buf);
|
||||
|
||||
ident->cache_start = g_list_previous (ident->cache_start);
|
||||
|
||||
/* now check if we have more buffers to push */
|
||||
if (ident->cache_start == NULL)
|
||||
{
|
||||
GST_DEBUG(0, "cache from %s is empty, changing loop function", GST_ELEMENT_NAME(ident));
|
||||
|
||||
/* free cache */
|
||||
g_list_free (ident->cache_end);
|
||||
ident->cache_end = NULL;
|
||||
|
||||
/* remove loop function */
|
||||
gst_element_set_loop_function (GST_ELEMENT (ident),
|
||||
(GstElementLoopFunction) GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
|
||||
gst_element_interrupt (GST_ELEMENT (ident));
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_spider_identity_handle_src_event (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
|
@ -561,15 +537,6 @@ gst_spider_identity_handle_src_event (GstPad *pad, GstEvent *event)
|
|||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH:
|
||||
case GST_EVENT_SEEK:
|
||||
/* see if there's something cached */
|
||||
if (ident->cache_start && ident->cache_start->data) {
|
||||
GST_DEBUG (0, "spider_identity seek in cache\n");
|
||||
/* FIXME we need to find the right position in the cache, make sure we
|
||||
* push from that offset and send out a discont event on the
|
||||
* next buffer */
|
||||
/* FIXME, we pass the event for now */
|
||||
/*return TRUE; */
|
||||
}
|
||||
default:
|
||||
res = gst_pad_event_default (pad, event);
|
||||
break;
|
||||
|
|
|
@ -57,10 +57,6 @@ struct _GstSpiderIdentity {
|
|||
/* plugged into autoplugger yet? */
|
||||
gboolean plugged;
|
||||
|
||||
/* caching */
|
||||
GList *cache_start;
|
||||
GList *cache_end;
|
||||
|
||||
/* Caps from typefinding */
|
||||
GstCaps *caps;
|
||||
|
||||
|
|
Loading…
Reference in a new issue