0


四、Plugin Request and Sometimes pads

Request and Sometimes pads

到目前为止,我们只处理了总是可用的pad。然而,也有一些pad仅在某些情况下创建,或者仅在应用程序请求pad时创建。第一个有时被称为a;第二个被称为请求pad。pad的可用性(always, sometimes or request)可以在pad的模板中看到。本章将讨论它们各自在什么时候有用,如何创建它们,以及何时处理它们。

Sometimes pads

“有时”pad是在特定条件下创建的pad,但不是在所有情况下创建的pad。这在很大程度上取决于流的内容:demuxers通常会解析流的首部,决定哪些基本流(视频、音频、字幕等)嵌入到系统流中,然后为每个基本流创建一个pad。根据自己的选择,它还可以为每个元素实例创建这些元素的多个实例。唯一的限制是每个新创建的pad都应该有一个唯一的名称。有时,当流数据被销毁时(即从暂停状态切换到就绪状态时),补码也会被销毁。

你不应该在EOS上处理pad,因为有人可能会重新激活管道并寻求回到流结束点之前。在EOS之后流应该仍然有效,至少在流数据被处理之前。在任何情况下,元素都是该pad的所有者

下面的示例代码将解析一个文本文件,其中第一行是一个数字(n)。接下来的行都以数字(0到n-1)开始,这是应该发送数据的源pad的编号。

3
0: foo
1: bar
0: boo
2: bye

解析此文件并创建动态“sometimes”pads的代码如下所示:

typedefstruct_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"));staticvoidgst_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));[..]}staticvoidgst_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)returnNULL;/* 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;}}}staticvoidgst_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);}

请注意,我们在每个地方都进行了大量检查,以确保文件中的内容是有效的。这样做有两个目的:首先,文件可能是错误的,在这种情况下,我们可以防止崩溃。第二个也是最重要的原因是——在极端情况下——该文件可能被恶意使用,导致插件中出现未定义的行为,这可能会导致安全问题。总是假定文件可能被用来做坏事。

Request pads

“请求”填充与有时填充类似,不同之处在于,请求是根据元素外部的内容而不是元素内部的内容创建的。这个概念经常用于muxers,对于将要放置在输出系统流中的每个基本流,将要求一个sink pad。它还可以用于具有可变数量输入或输出填充的元素中,例如tee(多输出)或input-selector(多输入)元素。

要实现请求填充,需要提供一个带有GST_PAD_REQUEST的padtemplate,并在GstElement中实现request_new_pad虚拟方法。为了进行清理,你需要实现release_pad虚拟方法。

static GstPad *gst_my_filter_request_new_pad(GstElement     *element,
                         GstPadTemplate *templ,const gchar    *name,const GstCaps  *caps);staticvoidgst_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"));staticvoidgst_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 */gst_element_add_pad(element, pad);return pad;}staticvoidgst_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);}
标签: ubuntu

本文转载自: https://blog.csdn.net/Creationyang/article/details/129143826
版权归原作者 李尔阳 所有, 如有侵权,请联系我们删除。

“四、Plugin Request and Sometimes pads”的评论:

还没有评论