From 3cc8f1412dba282c7141037b813e99a29eddc27d Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 28 Sep 2012 13:25:49 +0200 Subject: [PATCH] pwg: rework dynamic pads docs --- docs/pwg/advanced-request.xml | 129 +++++++++++++++++++++++++----------------- 1 file changed, 76 insertions(+), 53 deletions(-) diff --git a/docs/pwg/advanced-request.xml b/docs/pwg/advanced-request.xml index dc71d82..8ef9897 100644 --- a/docs/pwg/advanced-request.xml +++ b/docs/pwg/advanced-request.xml @@ -53,17 +53,18 @@ typedef struct _GstMyFilter { GList *srcpadlist; } GstMyFilter; +static GstStaticPadTemplate src_factory = +GST_STATIC_PAD_TEMPLATE ( + "src_%u", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("ANY") +); + static void -gst_my_filter_base_init (GstMyFilterClass *klass) +gst_my_filter_class_init (GstMyFilterClass *klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - static GstStaticPadTemplate src_factory = - GST_STATIC_PAD_TEMPLATE ( - "src_%02d", - GST_PAD_SRC, - GST_PAD_SOMETIMES, - GST_STATIC_CAPS ("ANY") - ); [..] gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_factory)); @@ -96,11 +97,11 @@ gst_my_filter_getline (GstMyFilter *filter) /* newline? */ if (data[n] == '\n') { - GstBuffer *buf = gst_buffer_new_and_alloc (n + 1); + GstBuffer *buf = gst_buffer_new_allocate (NULL, n + 1, NULL); gst_bytestream_peek_bytes (filter->bs, &data, n); - memcpy (GST_BUFFER_DATA (buf), data, n); - GST_BUFFER_DATA (buf)[n] = '\0'; + gst_buffer_fill (buf, 0, data, n); + gst_buffer_memset (buf, n, '\0', 1); gst_bytestream_flush_fast (filter->bs, n + 1); return buf; @@ -114,31 +115,33 @@ gst_my_filter_loopfunc (GstElement *element) GstMyFilter *filter = GST_MY_FILTER (element); GstBuffer *buf; GstPad *pad; + GstMapInfo map; gint num, n; /* parse header */ if (filter->firstrun) { - GstElementClass *klass; - GstPadTemplate *templ; gchar *padname; + guint8 id; if (!(buf = gst_my_filter_getline (filter))) { gst_element_error (element, STREAM, READ, (NULL), ("Stream contains no header")); return; } - num = atoi (GST_BUFFER_DATA (buf)); + gst_buffer_extract (buf, 0, &id, 1); + num = atoi (id); gst_buffer_unref (buf); /* for each of the streams, create a pad */ - klass = GST_ELEMENT_GET_CLASS (filter); - templ = gst_element_class_get_pad_template (klass, "src_%02d"); for (n = 0; n < num; n++) { - padname = g_strdup_printf ("src_%02d", n); - pad = gst_pad_new_from_template (templ, padname); + padname = g_strdup_printf ("src_%u", n); + pad = gst_pad_new_from_static_template (src_factory, padname); g_free (padname); - /* here, you would set _getcaps () and _link () functions */ + /* here, you would set _event () and _query () functions */ + + /* need to activate the pad before adding */ + gst_pad_set_active (pad, TRUE); gst_element_add_pad (element, pad); filter->srcpadlist = g_list_append (filter->srcpadlist, pad); @@ -153,36 +156,37 @@ gst_my_filter_loopfunc (GstElement *element) for (padlist = srcpadlist; padlist != NULL; padlist = g_list_next (padlist)) { pad = GST_PAD (padlist->data); - gst_event_ref (event); - gst_pad_push (pad, GST_DATA (event)); + gst_pad_push_event (pad, gst_event_ref (event)); } gst_event_unref (event); - gst_element_set_eos (element); - + /* pause the task here */ return; } /* parse stream number and go beyond the ':' in the data */ - num = atoi (GST_BUFFER_DATA (buf)); + gst_buffer_map (buf, &map, GST_MAP_READ); + num = atoi (map.data[0]); if (num >= 0 && num < g_list_length (filter->srcpadlist)) { pad = GST_PAD (g_list_nth_data (filter->srcpadlist, num); /* magic buffer parsing foo */ - for (n = 0; GST_BUFFER_DATA (buf)[n] != ':' && - GST_BUFFER_DATA (buf)[n] != '\0'; n++) ; - if (GST_BUFFER_DATA (buf)[n] != '\0') { + for (n = 0; map.data[n] != ':' && + map.data[n] != '\0'; n++) ; + if (map.data[n] != '\0') { GstBuffer *sub; - /* create subbuffer that starts right past the space. The reason + /* create region copy that starts right past the space. The reason * that we don't just forward the data pointer is because the * pointer is no longer the start of an allocated block of memory, * but just a pointer to a position somewhere in the middle of it. * That cannot be freed upon disposal, so we'd either crash or have - * a memleak. Creating a subbuffer is a simple way to solve that. */ - sub = gst_buffer_create_sub (buf, n + 1, GST_BUFFER_SIZE (buf) - n - 1); - gst_pad_push (pad, GST_DATA (sub)); + * a memleak. Creating a region copy is a simple way to solve that. */ + sub = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, + n + 1, map.size - n - 1); + gst_pad_push (pad, sub); } } + gst_buffer_unmap (buf, &map); gst_buffer_unref (buf); } ]]> @@ -207,46 +211,52 @@ gst_my_filter_loopfunc (GstElement *element) where - for each elementary stream that is to be placed in the output system stream - one sink pad will be requested. It can also be used in elements with a variable number of input or outputs pads, such as the - tee (multi-output), switch - or aggregator (both multi-input) elements. At the - time of writing this, it is unclear to me who is responsible for cleaning - up the created pad and how or when that should be done. Below is a simple - example of an aggregator based on request pads. + tee (multi-output) or + input-selector (multi-input) elements. + + + To implement request pads, you need to provide a padtemplate with a + GST_PAD_REQUEST presence and implement the + request_new_pad virtual method in + GstElement. + To clean up, you will need to implement the + release_pad virtual method. request_new_pad = gst_my_filter_request_new_pad; + element_class->release_pad = gst_my_filter_release_pad; } static GstPad * gst_my_filter_request_new_pad (GstElement *element, GstPadTemplate *templ, - const gchar *name) + const gchar *name, + const GstCaps *caps) { GstPad *pad; GstMyFilterInputContext *context; @@ -255,12 +265,25 @@ gst_my_filter_request_new_pad (GstElement *element, pad = gst_pad_new_from_template (templ, name); gst_pad_set_element_private (pad, context); - /* normally, you would set _link () and _getcaps () functions here */ + /* normally, you would set _chain () and _event () functions here */ gst_element_add_pad (element, pad); return pad; } + +static void +gst_my_filter_release_pad (GstElement *element, + GstPad *pad) +{ + GstMyFilterInputContext *context; + + context = gst_pad_get_element_private (pad); + g_free (context); + + gst_element_remove_pad (element, pad); +} + ]]> -- 2.7.4