GStreamer pwg: ch 12
12. Reqeust and Sometimes pads
sometimes pads
n 어떤 경우에 생성되는 pads
request pads
n application에서 요청 시 생성되는 pads
availability
n pad의 availability는 pad's template에 보임
12.1. sometimes pads
특정 조건 하에서만 생성되는 pads
보통 stream content에 의존하여 생성됨
n demuxer가 stream header를 parsing 후 elementary stream(audio, video, 자막 등)이 뭔지 파악
n 각 elementary stream 처리를 위한 (하나 이상의) pad를 생성
제약
n pad는 unique한 name을 지녀야 함
dispose 시점
n stream data가 dispose될 때 함께 dispose 됨
s i.e., from PAUSED to the READY state
s EOS 시점에서는 dispose 해서는 안 됨 (seek으로 re-activate 할 수 있음)
text file을 parsing하는 example code
3 | numbers |
0: foo | source pad의 number |
1: bar | |
0: boo | |
2: bye |
typedef struct _GstMyFilter { [..] gboolean firstrun; 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_class_init (GstMyFilterClass *klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); [..] gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_factory)); [..] } static void gst_my_filter_init (GstMyFilter *filter) { [..] filter->firstrun = TRUE; filter->srcpadlist = NULL; } /* * Get one line of data - without newline. */ static GstBuffer * gst_my_filter_getline (GstMyFilter *filter) { guint8 *data; gint n, num; /* max. line length is 512 characters - for safety */ for (n = 0; n < 512; n++) { num = gst_bytestream_peek_bytes (filter->bs, &data, n + 1); if (num != n + 1) return NULL; /* newline? */ if (data[n] == '\n') { GstBuffer *buf = gst_buffer_new_allocate (NULL, n + 1, NULL); gst_bytestream_peek_bytes (filter->bs, &data, n); gst_buffer_fill (buf, 0, data, n); gst_buffer_memset (buf, n, '\0', 1); gst_bytestream_flush_fast (filter->bs, n + 1); return buf; } } } static void 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) { gchar *padname; guint8 id; if (!(buf = gst_my_filter_getline (filter))) { gst_element_error (element, STREAM, READ, (NULL), ("Stream contains no header")); return; } gst_buffer_extract (buf, 0, &id, 1); num = atoi (id); gst_buffer_unref (buf); /* for each of the streams, create a pad */ for (n = 0; n < num; n++) { padname = g_strdup_printf ("src_%u", n); pad = gst_pad_new_from_static_template (src_factory, padname); g_free (padname); /* 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); } } /* and now, simply parse each line and push over */ if (!(buf = gst_my_filter_getline (filter))) { GstEvent *event = gst_event_new (GST_EVENT_EOS); GList *padlist; for (padlist = srcpadlist; padlist != NULL; padlist = g_list_next (padlist)) { pad = GST_PAD (padlist->data); gst_pad_push_event (pad, gst_event_ref (event)); } gst_event_unref (event); /* pause the task here */ return; } /* parse stream number and go beyond the ':' in the data */ 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; map.data[n] != ':' && map.data[n] != '\0'; n++) ; if (map.data[n] != '\0') { GstBuffer *sub; /* 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 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); } |
file이 깨져있던가, 혹은 악의적인 file content에 대해 valid 여부를 check
n i.e., buffer overflow
12.2. Request pads
sometimes pads와 유사함
차이는 request는 On-demand 시점에서 생성됨
muxer에서 보통 사용됨
output system stream 내에 위치하는 각각의 elementary stream에 대해
하나의 sink pad가 요청될 수 있음
가변 input/output pads를 지닌 element에서 사용될 수 있음
n i.e. tee, input-selector(multi-input) elements
pad template을 GST_PAD_REQUEST로 제공해서 구현할 수 있음
GstElement의 request_new_pad virtual method를 구현해야함
request_new_pad
release_pad
n clean up에 사용
static GstPad * gst_my_filter_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name, const GstCaps *caps); static void gst_my_filter_release_pad (GstElement *element, GstPad *pad); static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( "sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, GST_STATIC_CAPS ("ANY") ); static void gst_my_filter_class_init (GstMyFilterClass *klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); [..] gst_element_class_add_pad_template (klass, gst_static_pad_template_get (&sink_factory)); [..] element_class->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 GstCaps *caps) { GstPad *pad; GstMyFilterInputContext *context; context = g_new0 (GstMyFilterInputContext, 1); pad = gst_pad_new_from_template (templ, name); gst_pad_set_element_private (pad, context); /* normally, you would set _chain () and _event () functions here */ // set _chain or _event for the created pad 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); } |
'Multimedia > GStreamer' 카테고리의 다른 글
GStreamer pwg ch 7 ~ 9 (0) | 2021.12.22 |
---|---|
GStreamer pwg ch 11 (0) | 2021.12.22 |
GStreamer pwg: ch 13 (0) | 2021.12.22 |
GStreamer pwg: ch. 13 part 1 (0) | 2021.12.22 |
GStreamer pwg: ch 13 part 2 (0) | 2021.12.22 |
댓글