gstreamer_core/gst/gstghostpad.c
changeset 16 8e837d1bf446
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
15:4b0c6ed43234 16:8e837d1bf446
    54 #include <glib_global.h>
    54 #include <glib_global.h>
    55 #endif
    55 #endif
    56 
    56 
    57 #define GST_CAT_DEFAULT GST_CAT_PADS
    57 #define GST_CAT_DEFAULT GST_CAT_PADS
    58 
    58 
    59 #define GST_TYPE_PROXY_PAD              (gst_proxy_pad_get_type ())
       
    60 #define GST_IS_PROXY_PAD(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PROXY_PAD))
       
    61 #define GST_IS_PROXY_PAD_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PROXY_PAD))
       
    62 #define GST_PROXY_PAD(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROXY_PAD, GstProxyPad))
       
    63 #define GST_PROXY_PAD_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PROXY_PAD, GstProxyPadClass))
       
    64 #define GST_PROXY_PAD_CAST(obj)         ((GstProxyPad *)obj)
    59 #define GST_PROXY_PAD_CAST(obj)         ((GstProxyPad *)obj)
    65 
    60 #define GST_PROXY_PAD_PRIVATE(obj)      (GST_PROXY_PAD_CAST (obj)->priv)
    66 #define GST_PROXY_PAD_TARGET(pad)       (GST_PROXY_PAD_CAST (pad)->target)
    61 #define GST_PROXY_PAD_TARGET(pad)       (GST_PROXY_PAD_PRIVATE (pad)->target)
    67 #define GST_PROXY_PAD_INTERNAL(pad)     (GST_PROXY_PAD_CAST (pad)->internal)
    62 #define GST_PROXY_PAD_INTERNAL(pad)     (GST_PROXY_PAD_PRIVATE (pad)->internal)
    68 
    63 #define GST_PROXY_PAD_RETARGET(pad)     (GST_PROXY_PAD_PRIVATE (pad)->retarget)
    69 typedef struct _GstProxyPad GstProxyPad;
    64 #define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_PRIVATE (pad)->proxy_lock)
    70 typedef struct _GstProxyPadClass GstProxyPadClass;
       
    71 
       
    72 #define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_CAST (pad)->proxy_lock)
       
    73 #define GST_PROXY_LOCK(pad)     (g_mutex_lock (GST_PROXY_GET_LOCK (pad)))
    65 #define GST_PROXY_LOCK(pad)     (g_mutex_lock (GST_PROXY_GET_LOCK (pad)))
    74 #define GST_PROXY_UNLOCK(pad)   (g_mutex_unlock (GST_PROXY_GET_LOCK (pad)))
    66 #define GST_PROXY_UNLOCK(pad)   (g_mutex_unlock (GST_PROXY_GET_LOCK (pad)))
    75 
    67 
    76 struct _GstProxyPad
    68 struct _GstProxyPadPrivate
    77 {
    69 {
    78   GstPad pad;
       
    79 
       
    80   /* with PROXY_LOCK */
    70   /* with PROXY_LOCK */
    81   GMutex *proxy_lock;
    71   GMutex *proxy_lock;
    82   GstPad *target;
    72   GstPad *target;
    83   GstPad *internal;
    73   GstPad *internal;
       
    74   gboolean retarget;
    84 };
    75 };
    85 
       
    86 struct _GstProxyPadClass
       
    87 {
       
    88   GstPadClass parent_class;
       
    89 
       
    90   /*< private > */
       
    91   gpointer _gst_reserved[1];
       
    92 };
       
    93 
       
    94 static GType gst_proxy_pad_get_type (void);
       
    95 
    76 
    96 G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
    77 G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
    97 
    78 
    98 static GstPad *gst_proxy_pad_get_target (GstPad * pad);
    79 static GstPad *gst_proxy_pad_get_target (GstPad * pad);
    99 
    80 
   103 #ifndef GST_DISABLE_LOADSAVE
    84 #ifndef GST_DISABLE_LOADSAVE
   104 static xmlNodePtr gst_proxy_pad_save_thyself (GstObject * object,
    85 static xmlNodePtr gst_proxy_pad_save_thyself (GstObject * object,
   105     xmlNodePtr parent);
    86     xmlNodePtr parent);
   106 #endif
    87 #endif
   107 
    88 
       
    89 static void on_src_target_notify (GstPad * target,
       
    90     GParamSpec * unused, GstGhostPad * pad);
       
    91 
   108 
    92 
   109 static void
    93 static void
   110 gst_proxy_pad_class_init (GstProxyPadClass * klass)
    94 gst_proxy_pad_class_init (GstProxyPadClass * klass)
   111 {
    95 {
   112   GObjectClass *gobject_class = (GObjectClass *) klass;
    96   GObjectClass *gobject_class = (GObjectClass *) klass;
       
    97 
       
    98   g_type_class_add_private (klass, sizeof (GstProxyPadPrivate));
   113 
    99 
   114   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_proxy_pad_dispose);
   100   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_proxy_pad_dispose);
   115   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_proxy_pad_finalize);
   101   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_proxy_pad_finalize);
   116 
   102 
   117 #ifndef GST_DISABLE_LOADSAVE
   103 #ifndef GST_DISABLE_LOADSAVE
   160   }
   146   }
   161 
   147 
   162   return res;
   148   return res;
   163 }
   149 }
   164 
   150 
   165 static GList *
   151 static GstIterator *
   166 gst_proxy_pad_do_internal_link (GstPad * pad)
   152 gst_proxy_pad_do_iterate_internal_links (GstPad * pad)
   167 {
   153 {
   168   GList *res = NULL;
   154   GstIterator *res = NULL;
   169   GstPad *target = gst_proxy_pad_get_target (pad);
   155   GstPad *target = gst_proxy_pad_get_target (pad);
   170 
   156 
   171   if (target) {
   157   if (target) {
   172     res = gst_pad_get_internal_links (target);
   158     res = gst_pad_iterate_internal_links (target);
   173     gst_object_unref (target);
   159     gst_object_unref (target);
   174   }
   160   }
   175 
   161 
   176   return res;
   162   return res;
   177 }
   163 }
   193 {
   179 {
   194   GstFlowReturn res;
   180   GstFlowReturn res;
   195   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
   181   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
   196 
   182 
   197   res = gst_pad_push (internal, buffer);
   183   res = gst_pad_push (internal, buffer);
       
   184 
       
   185   return res;
       
   186 }
       
   187 
       
   188 static GstFlowReturn
       
   189 gst_proxy_pad_do_chain_list (GstPad * pad, GstBufferList * list)
       
   190 {
       
   191   GstFlowReturn res;
       
   192   GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
       
   193 
       
   194   res = gst_pad_push_list (internal, list);
   198 
   195 
   199   return res;
   196   return res;
   200 }
   197 }
   201 
   198 
   202 static GstFlowReturn
   199 static GstFlowReturn
   232   if (target) {
   229   if (target) {
   233     /* if we have a real target, proxy the call */
   230     /* if we have a real target, proxy the call */
   234     res = gst_pad_get_caps (target);
   231     res = gst_pad_get_caps (target);
   235     gst_object_unref (target);
   232     gst_object_unref (target);
   236 
   233 
   237     GST_DEBUG_OBJECT (pad, "get caps of target: %" GST_PTR_FORMAT, res);
   234     GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
       
   235         GST_DEBUG_PAD_NAME (target), res);
   238 
   236 
   239     /* filter against the template */
   237     /* filter against the template */
   240     if (templ && res) {
   238     if (templ && res) {
   241       GstCaps *filt, *tmp;
   239       GstCaps *filt, *tmp;
   242 
   240 
   329       goto wrong_direction;
   327       goto wrong_direction;
   330   } else
   328   } else
   331     GST_LOG_OBJECT (pad, "clearing target");
   329     GST_LOG_OBJECT (pad, "clearing target");
   332 
   330 
   333   /* clear old target */
   331   /* clear old target */
   334   if ((oldtarget = GST_PROXY_PAD_TARGET (pad))) {
   332   if ((oldtarget = GST_PROXY_PAD_TARGET (pad)))
   335     gst_object_unref (oldtarget);
   333     gst_object_unref (oldtarget);
   336   }
   334 
   337   /* set and ref new target if any */
   335   /* set and ref new target if any */
   338   if (target)
   336   if (target)
   339     GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
   337     GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
   340   else
   338   else
   341     GST_PROXY_PAD_TARGET (pad) = NULL;
   339     GST_PROXY_PAD_TARGET (pad) = NULL;
   373   if (target)
   371   if (target)
   374     gst_object_ref (target);
   372     gst_object_ref (target);
   375   GST_PROXY_UNLOCK (pad);
   373   GST_PROXY_UNLOCK (pad);
   376 
   374 
   377   return target;
   375   return target;
       
   376 }
       
   377 
       
   378 static void
       
   379 gst_proxy_pad_do_unlink (GstPad * pad)
       
   380 {
       
   381   GstPad *internal;
       
   382 
       
   383   /* don't do anything if this unlink resulted from retargeting the pad
       
   384    * controlled by the ghostpad. We only want to invalidate the target pad when
       
   385    * the element suddently unlinked with our internal pad. */
       
   386   if (GST_PROXY_PAD_RETARGET (pad))
       
   387     return;
       
   388 
       
   389   internal = GST_PROXY_PAD_INTERNAL (pad);
       
   390 
       
   391   GST_DEBUG_OBJECT (pad, "pad is unlinked");
       
   392 
       
   393   gst_proxy_pad_set_target (internal, NULL);
   378 }
   394 }
   379 
   395 
   380 static void
   396 static void
   381 gst_proxy_pad_dispose (GObject * object)
   397 gst_proxy_pad_dispose (GObject * object)
   382 {
   398 {
   398 static void
   414 static void
   399 gst_proxy_pad_finalize (GObject * object)
   415 gst_proxy_pad_finalize (GObject * object)
   400 {
   416 {
   401   GstProxyPad *pad = GST_PROXY_PAD (object);
   417   GstProxyPad *pad = GST_PROXY_PAD (object);
   402 
   418 
   403   g_mutex_free (pad->proxy_lock);
   419   g_mutex_free (GST_PROXY_GET_LOCK (pad));
   404   pad->proxy_lock = NULL;
   420   GST_PROXY_GET_LOCK (pad) = NULL;
   405 
   421 
   406   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
   422   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
   407 }
   423 }
   408 
   424 
   409 static void
   425 static void
   410 gst_proxy_pad_init (GstProxyPad * ppad)
   426 gst_proxy_pad_init (GstProxyPad * ppad)
   411 {
   427 {
   412   GstPad *pad = (GstPad *) ppad;
   428   GstPad *pad = (GstPad *) ppad;
   413 
   429 
   414   ppad->proxy_lock = g_mutex_new ();
   430   GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad,
       
   431       GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
       
   432   GST_PROXY_GET_LOCK (pad) = g_mutex_new ();
   415 
   433 
   416   gst_pad_set_query_type_function (pad,
   434   gst_pad_set_query_type_function (pad,
   417       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type));
   435       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type));
   418   gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event));
   436   gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event));
   419   gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query));
   437   gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query));
   420   gst_pad_set_internal_link_function (pad,
   438   gst_pad_set_iterate_internal_links_function (pad,
   421       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_internal_link));
   439       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_iterate_internal_links));
   422 
   440 
   423   gst_pad_set_getcaps_function (pad,
   441   gst_pad_set_getcaps_function (pad,
   424       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps));
   442       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps));
   425   gst_pad_set_acceptcaps_function (pad,
   443   gst_pad_set_acceptcaps_function (pad,
   426       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_acceptcaps));
   444       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_acceptcaps));
   427   gst_pad_set_fixatecaps_function (pad,
   445   gst_pad_set_fixatecaps_function (pad,
   428       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps));
   446       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps));
   429   gst_pad_set_setcaps_function (pad,
   447   gst_pad_set_setcaps_function (pad,
   430       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps));
   448       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps));
       
   449   gst_pad_set_unlink_function (pad,
       
   450       GST_DEBUG_FUNCPTR (gst_proxy_pad_do_unlink));
   431 }
   451 }
   432 
   452 
   433 #ifndef GST_DISABLE_LOADSAVE
   453 #ifndef GST_DISABLE_LOADSAVE
   434 /**
   454 /**
   435  * gst_proxy_pad_save_thyself:
   455  * gst_proxy_pad_save_thyself:
   488 /***********************************************************************
   508 /***********************************************************************
   489  * Ghost pads, implemented as a pair of proxy pads (sort of)
   509  * Ghost pads, implemented as a pair of proxy pads (sort of)
   490  */
   510  */
   491 
   511 
   492 
   512 
   493 struct _GstGhostPad
   513 #define GST_GHOST_PAD_PRIVATE(obj)	(GST_GHOST_PAD_CAST (obj)->priv)
   494 {
   514 
   495   GstProxyPad pad;
   515 struct _GstGhostPadPrivate
   496 
   516 {
   497   /* with PROXY_LOCK */
   517   /* with PROXY_LOCK */
   498   gulong notify_id;
   518   gulong notify_id;
   499 
   519 
   500   /*< private > */
   520   gboolean constructed;
   501   gpointer _gst_reserved[GST_PADDING];
       
   502 };
   521 };
   503 
       
   504 struct _GstGhostPadClass
       
   505 {
       
   506   GstProxyPadClass parent_class;
       
   507 
       
   508   /*< private > */
       
   509   gpointer _gst_reserved[GST_PADDING];
       
   510 };
       
   511 
       
   512 
   522 
   513 G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
   523 G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
   514 
   524 
   515 static void gst_ghost_pad_dispose (GObject * object);
   525 static void gst_ghost_pad_dispose (GObject * object);
   516 
   526 
   517 static void
   527 static void
   518 gst_ghost_pad_class_init (GstGhostPadClass * klass)
   528 gst_ghost_pad_class_init (GstGhostPadClass * klass)
   519 {
   529 {
   520   GObjectClass *gobject_class = (GObjectClass *) klass;
   530   GObjectClass *gobject_class = (GObjectClass *) klass;
       
   531 
       
   532   g_type_class_add_private (klass, sizeof (GstGhostPadPrivate));
   521 
   533 
   522   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose);
   534   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose);
   523 }
   535 }
   524 
   536 
   525 /* see gstghostpad design docs */
   537 /* see gstghostpad design docs */
   660 }
   672 }
   661 
   673 
   662 static void
   674 static void
   663 gst_ghost_pad_do_unlink (GstPad * pad)
   675 gst_ghost_pad_do_unlink (GstPad * pad)
   664 {
   676 {
   665   GstPad *target;
       
   666   GstPad *internal;
   677   GstPad *internal;
   667 
   678 
   668   target = gst_proxy_pad_get_target (pad);
       
   669   internal = GST_PROXY_PAD_INTERNAL (pad);
   679   internal = GST_PROXY_PAD_INTERNAL (pad);
   670 
   680 
   671   GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
   681   GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
   672 
   682 
   673   /* The target of the internal pad is no longer valid */
   683   /* The target of the internal pad is no longer valid */
   674   gst_proxy_pad_set_target (internal, NULL);
   684   gst_proxy_pad_set_target (internal, NULL);
   675 
       
   676   if (target) {
       
   677     if (GST_PAD_UNLINKFUNC (target))
       
   678       GST_PAD_UNLINKFUNC (target) (target);
       
   679 
       
   680     gst_object_unref (target);
       
   681   }
       
   682 }
   685 }
   683 
   686 
   684 static void
   687 static void
   685 on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad)
   688 on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad)
   686 {
   689 {
   687   GstCaps *caps;
   690   GstCaps *caps;
       
   691   gboolean changed;
   688 
   692 
   689   g_object_get (internal, "caps", &caps, NULL);
   693   g_object_get (internal, "caps", &caps, NULL);
   690 
   694 
   691   GST_OBJECT_LOCK (pad);
   695   GST_OBJECT_LOCK (pad);
       
   696   changed = (GST_PAD_CAPS (pad) != caps);
       
   697   if (changed)
       
   698     gst_caps_replace (&(GST_PAD_CAPS (pad)), caps);
       
   699   GST_OBJECT_UNLOCK (pad);
       
   700 
       
   701   if (changed)
       
   702     g_object_notify (G_OBJECT (pad), "caps");
       
   703 
       
   704   if (caps)
       
   705     gst_caps_unref (caps);
       
   706 }
       
   707 
       
   708 static void
       
   709 on_src_target_notify (GstPad * target, GParamSpec * unused, GstGhostPad * pad)
       
   710 {
       
   711   GstCaps *caps;
       
   712   gboolean changed;
       
   713 
       
   714   g_object_get (target, "caps", &caps, NULL);
       
   715 
       
   716   GST_OBJECT_LOCK (pad);
       
   717   changed = (GST_PAD_CAPS (pad) != caps);
   692   gst_caps_replace (&(GST_PAD_CAPS (pad)), caps);
   718   gst_caps_replace (&(GST_PAD_CAPS (pad)), caps);
   693   GST_OBJECT_UNLOCK (pad);
   719   GST_OBJECT_UNLOCK (pad);
   694 
   720 
   695   g_object_notify (G_OBJECT (pad), "caps");
   721   if (changed)
       
   722     g_object_notify (G_OBJECT (pad), "caps");
       
   723 
   696   if (caps)
   724   if (caps)
   697     gst_caps_unref (caps);
   725     gst_caps_unref (caps);
   698 }
   726 }
   699 
   727 
       
   728 static gboolean
       
   729 gst_ghost_pad_do_setcaps (GstPad * pad, GstCaps * caps)
       
   730 {
       
   731   if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
       
   732     return TRUE;
       
   733 
       
   734   return gst_proxy_pad_do_setcaps (pad, caps);
       
   735 }
       
   736 
   700 static void
   737 static void
   701 gst_ghost_pad_init (GstGhostPad * pad)
   738 gst_ghost_pad_init (GstGhostPad * pad)
   702 {
   739 {
       
   740   GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
       
   741       GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
       
   742 
       
   743   gst_pad_set_setcaps_function (GST_PAD_CAST (pad),
       
   744       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_setcaps));
   703   gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
   745   gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
   704       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_pull));
   746       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_pull));
   705   gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
   747   gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
   706       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_push));
   748       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_push));
   707 }
   749 }
   709 static void
   751 static void
   710 gst_ghost_pad_dispose (GObject * object)
   752 gst_ghost_pad_dispose (GObject * object)
   711 {
   753 {
   712   GstPad *pad;
   754   GstPad *pad;
   713   GstPad *internal;
   755   GstPad *internal;
   714   GstPad *intpeer;
   756   GstPad *peer;
   715 
   757 
   716   pad = GST_PAD (object);
   758   pad = GST_PAD (object);
   717 
   759 
   718   GST_DEBUG_OBJECT (pad, "dispose");
   760   GST_DEBUG_OBJECT (pad, "dispose");
       
   761 
       
   762   gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
       
   763 
       
   764   /* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to
       
   765    * gst_ghost_pad_do_unlink when the ghost pad is in an inconsistent state */
       
   766   peer = gst_pad_get_peer (pad);
       
   767   if (peer) {
       
   768     if (GST_PAD_IS_SRC (pad))
       
   769       gst_pad_unlink (pad, peer);
       
   770     else
       
   771       gst_pad_unlink (peer, pad);
       
   772 
       
   773     gst_object_unref (peer);
       
   774   }
   719 
   775 
   720   GST_PROXY_LOCK (pad);
   776   GST_PROXY_LOCK (pad);
   721   internal = GST_PROXY_PAD_INTERNAL (pad);
   777   internal = GST_PROXY_PAD_INTERNAL (pad);
   722 
   778 
   723   gst_pad_set_activatepull_function (internal, NULL);
   779   gst_pad_set_activatepull_function (internal, NULL);
   724   gst_pad_set_activatepush_function (internal, NULL);
   780   gst_pad_set_activatepush_function (internal, NULL);
   725 
   781 
   726   g_signal_handler_disconnect (internal, GST_GHOST_PAD_CAST (pad)->notify_id);
   782   g_signal_handler_disconnect (internal,
   727 
   783       GST_GHOST_PAD_PRIVATE (pad)->notify_id);
   728   intpeer = gst_pad_get_peer (internal);
       
   729   if (intpeer) {
       
   730     if (GST_PAD_IS_SRC (internal))
       
   731       gst_pad_unlink (internal, intpeer);
       
   732     else
       
   733       gst_pad_unlink (intpeer, internal);
       
   734 
       
   735     gst_object_unref (intpeer);
       
   736   }
       
   737 
       
   738   GST_PROXY_PAD_INTERNAL (internal) = NULL;
       
   739 
   784 
   740   /* disposes of the internal pad, since the ghostpad is the only possible object
   785   /* disposes of the internal pad, since the ghostpad is the only possible object
   741    * that has a refcount on the internal pad. */
   786    * that has a refcount on the internal pad. */
   742   gst_object_unparent (GST_OBJECT_CAST (internal));
   787   gst_object_unparent (GST_OBJECT_CAST (internal));
       
   788   GST_PROXY_PAD_INTERNAL (pad) = NULL;
   743 
   789 
   744   GST_PROXY_UNLOCK (pad);
   790   GST_PROXY_UNLOCK (pad);
   745 
   791 
   746   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
   792   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
   747 }
   793 }
   748 
   794 
   749 static GstPad *
   795 /**
   750 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
   796  * gst_ghost_pad_construct:
   751     GstPadTemplate * templ)
   797  * @gpad: the newly allocated ghost pad
   752 {
   798  *
   753   GstPad *ret;
   799  * Finish initialization of a newly allocated ghost pad.
   754   GstPad *internal;
   800  *
   755   GstPadDirection otherdir;
   801  * This function is most useful in language bindings and when subclassing
   756 
   802  * #GstGhostPad; plugin and application developers normally will not call this
   757   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
   803  * function. Call this function directly after a call to g_object_new
   758 
   804  * (GST_TYPE_GHOST_PAD, "direction", @dir, ..., NULL).
   759   /* OBJECT CREATION */
   805  *
   760   if (templ) {
   806  * Returns: %TRUE if the construction succeeds, %FALSE otherwise.
   761     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
   807  *
   762         "direction", dir, "template", templ, NULL);
   808  * Since: 0.10.22
   763   } else {
   809  */
   764     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
   810 #ifdef __SYMBIAN32__
   765         "direction", dir, NULL);
   811 EXPORT_C
   766   }
   812 #endif
       
   813 
       
   814 gboolean
       
   815 gst_ghost_pad_construct (GstGhostPad * gpad)
       
   816 {
       
   817   GstPadDirection dir, otherdir;
       
   818   GstPadTemplate *templ;
       
   819   GstPad *pad, *internal;
       
   820 
       
   821   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
       
   822   g_return_val_if_fail (GST_GHOST_PAD_PRIVATE (gpad)->constructed == FALSE,
       
   823       FALSE);
       
   824 
       
   825   g_object_get (gpad, "direction", &dir, "template", &templ, NULL);
       
   826 
       
   827   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, FALSE);
       
   828 
       
   829   pad = GST_PAD (gpad);
   767 
   830 
   768   /* Set directional padfunctions for ghostpad */
   831   /* Set directional padfunctions for ghostpad */
   769   if (dir == GST_PAD_SINK) {
   832   if (dir == GST_PAD_SINK) {
   770     gst_pad_set_bufferalloc_function (ret,
   833     gst_pad_set_bufferalloc_function (pad,
   771         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
   834         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
   772     gst_pad_set_chain_function (ret,
   835     gst_pad_set_chain_function (pad,
   773         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
   836         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
       
   837     gst_pad_set_chain_list_function (pad,
       
   838         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain_list));
   774   } else {
   839   } else {
   775     gst_pad_set_getrange_function (ret,
   840     gst_pad_set_getrange_function (pad,
   776         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
   841         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
   777     gst_pad_set_checkgetrange_function (ret,
   842     gst_pad_set_checkgetrange_function (pad,
   778         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
   843         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
   779   }
   844   }
   780 
   845 
   781   /* link/unlink functions */
   846   /* link/unlink functions */
   782   gst_pad_set_link_function (ret, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link));
   847   gst_pad_set_link_function (pad, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link));
   783   gst_pad_set_unlink_function (ret,
   848   gst_pad_set_unlink_function (pad,
   784       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink));
   849       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink));
   785 
       
   786 
   850 
   787   /* INTERNAL PAD, it always exists and is child of the ghostpad */
   851   /* INTERNAL PAD, it always exists and is child of the ghostpad */
   788   otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
   852   otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
   789   if (templ) {
   853   if (templ) {
   790     internal =
   854     internal =
   791         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
   855         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
   792         "direction", otherdir, "template", templ, NULL);
   856         "direction", otherdir, "template", templ, NULL);
       
   857     /* release ref obtained via g_object_get */
       
   858     gst_object_unref (templ);
   793   } else {
   859   } else {
   794     internal =
   860     internal =
   795         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
   861         g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
   796         "direction", otherdir, NULL);
   862         "direction", otherdir, NULL);
   797   }
   863   }
   801   if (dir == GST_PAD_SRC) {
   867   if (dir == GST_PAD_SRC) {
   802     gst_pad_set_bufferalloc_function (internal,
   868     gst_pad_set_bufferalloc_function (internal,
   803         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
   869         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
   804     gst_pad_set_chain_function (internal,
   870     gst_pad_set_chain_function (internal,
   805         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
   871         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
       
   872     gst_pad_set_chain_list_function (internal,
       
   873         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain_list));
   806   } else {
   874   } else {
   807     gst_pad_set_getrange_function (internal,
   875     gst_pad_set_getrange_function (internal,
   808         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
   876         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
   809     gst_pad_set_checkgetrange_function (internal,
   877     gst_pad_set_checkgetrange_function (internal,
   810         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
   878         GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
   811   }
   879   }
   812 
   880 
   813   GST_PROXY_LOCK (ret);
   881   GST_PROXY_LOCK (pad);
   814 
   882 
   815   /* now make the ghostpad a parent of the internal pad */
   883   /* now make the ghostpad a parent of the internal pad */
   816   if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
   884   if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
   817           GST_OBJECT_CAST (ret)))
   885           GST_OBJECT_CAST (pad)))
   818     goto parent_failed;
   886     goto parent_failed;
   819 
   887 
   820   /* The ghostpad is the parent of the internal pad and is the only object that
   888   /* The ghostpad is the parent of the internal pad and is the only object that
   821    * can have a refcount on the internal pad.
   889    * can have a refcount on the internal pad.
   822    * At this point, the GstGhostPad has a refcount of 1, and the internal pad has
   890    * At this point, the GstGhostPad has a refcount of 1, and the internal pad has
   823    * a refcount of 1.
   891    * a refcount of 1.
   824    * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
   892    * When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
   825    * it's refcount on the internal pad in the dispose method by un-parenting it.
   893    * it's refcount on the internal pad in the dispose method by un-parenting it.
   826    * This is why we don't take extra refcounts in the assignments below
   894    * This is why we don't take extra refcounts in the assignments below
   827    */
   895    */
   828   GST_PROXY_PAD_INTERNAL (ret) = internal;
   896   GST_PROXY_PAD_INTERNAL (pad) = internal;
   829   GST_PROXY_PAD_INTERNAL (internal) = ret;
   897   GST_PROXY_PAD_INTERNAL (internal) = pad;
   830 
   898 
   831   /* could be more general here, iterating over all writable properties...
   899   /* could be more general here, iterating over all writable properties...
   832    * taking the short road for now tho */
   900    * taking the short road for now tho */
   833   GST_GHOST_PAD_CAST (ret)->notify_id =
   901   GST_GHOST_PAD_PRIVATE (pad)->notify_id =
   834       g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify),
   902       g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify),
   835       ret);
   903       pad);
   836 
   904 
   837   /* call function to init values of the pad caps */
   905   /* call function to init values of the pad caps */
   838   on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (ret));
   906   on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (pad));
   839 
   907 
   840   /* special activation functions for the internal pad */
   908   /* special activation functions for the internal pad */
   841   gst_pad_set_activatepull_function (internal,
   909   gst_pad_set_activatepull_function (internal,
   842       GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_pull));
   910       GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_pull));
   843   gst_pad_set_activatepush_function (internal,
   911   gst_pad_set_activatepush_function (internal,
   844       GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push));
   912       GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push));
   845 
   913 
   846   GST_PROXY_UNLOCK (ret);
   914   GST_PROXY_UNLOCK (pad);
   847 
   915 
   848   return ret;
   916   GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
       
   917   return TRUE;
   849 
   918 
   850   /* ERRORS */
   919   /* ERRORS */
   851 parent_failed:
   920 parent_failed:
   852   {
   921   {
   853     GST_WARNING_OBJECT (ret, "Could not set internal pad %s:%s",
   922     GST_WARNING_OBJECT (gpad, "Could not set internal pad %s:%s",
   854         GST_DEBUG_PAD_NAME (internal));
   923         GST_DEBUG_PAD_NAME (internal));
   855     g_critical ("Could not set internal pad %s:%s",
   924     g_critical ("Could not set internal pad %s:%s",
   856         GST_DEBUG_PAD_NAME (internal));
   925         GST_DEBUG_PAD_NAME (internal));
   857     GST_PROXY_UNLOCK (ret);
   926     GST_PROXY_UNLOCK (pad);
   858     gst_object_unref (ret);
       
   859     gst_object_unref (internal);
   927     gst_object_unref (internal);
   860     return NULL;
   928     return FALSE;
   861   }
   929   }
       
   930 }
       
   931 
       
   932 static GstPad *
       
   933 gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
       
   934     GstPadTemplate * templ)
       
   935 {
       
   936   GstGhostPad *ret;
       
   937 
       
   938   g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
       
   939 
       
   940   /* OBJECT CREATION */
       
   941   if (templ) {
       
   942     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
       
   943         "direction", dir, "template", templ, NULL);
       
   944   } else {
       
   945     ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
       
   946         "direction", dir, NULL);
       
   947   }
       
   948 
       
   949   if (!gst_ghost_pad_construct (ret))
       
   950     goto construct_failed;
       
   951 
       
   952   return GST_PAD (ret);
       
   953 
       
   954 construct_failed:
       
   955   /* already logged */
       
   956   gst_object_unref (ret);
       
   957   return NULL;
   862 }
   958 }
   863 
   959 
   864 /**
   960 /**
   865  * gst_ghost_pad_new_no_target:
   961  * gst_ghost_pad_new_no_target:
   866  * @name: the name of the new pad, or NULL to assign a default name.
   962  * @name: the name of the new pad, or NULL to assign a default name.
  1047  * gst_ghost_pad_set_target:
  1143  * gst_ghost_pad_set_target:
  1048  * @gpad: the #GstGhostpad
  1144  * @gpad: the #GstGhostpad
  1049  * @newtarget: the new pad target
  1145  * @newtarget: the new pad target
  1050  *
  1146  *
  1051  * Set the new target of the ghostpad @gpad. Any existing target
  1147  * Set the new target of the ghostpad @gpad. Any existing target
  1052  * is unlinked and links to the new target are established.
  1148  * is unlinked and links to the new target are established. if @newtarget is
       
  1149  * NULL the target will be cleared.
  1053  *
  1150  *
  1054  * Returns: TRUE if the new target could be set. This function can return FALSE
  1151  * Returns: TRUE if the new target could be set. This function can return FALSE
  1055  * when the internal pads could not be linked.
  1152  * when the internal pads could not be linked.
  1056  */
  1153  */
  1057 #ifdef __SYMBIAN32__
  1154 #ifdef __SYMBIAN32__
  1068 
  1165 
  1069   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
  1166   g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
  1070 
  1167 
  1071   GST_PROXY_LOCK (gpad);
  1168   GST_PROXY_LOCK (gpad);
  1072   internal = GST_PROXY_PAD_INTERNAL (gpad);
  1169   internal = GST_PROXY_PAD_INTERNAL (gpad);
  1073 
  1170   g_assert (internal);
  1074   GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
  1171 
       
  1172   if (newtarget)
       
  1173     GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
       
  1174   else
       
  1175     GST_DEBUG_OBJECT (gpad, "clearing target");
  1075 
  1176 
  1076   /* clear old target */
  1177   /* clear old target */
  1077   if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
  1178   if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
  1078     /* if we have an internal pad, unlink */
  1179     if (GST_PAD_IS_SRC (oldtarget)) {
  1079     if (internal) {
  1180       g_signal_handlers_disconnect_by_func (oldtarget,
  1080       if (GST_PAD_IS_SRC (internal))
  1181           (gpointer) on_src_target_notify, gpad);
  1081         gst_pad_unlink (internal, oldtarget);
       
  1082       else
       
  1083         gst_pad_unlink (oldtarget, internal);
       
  1084     }
  1182     }
       
  1183 
       
  1184     GST_PROXY_PAD_RETARGET (internal) = TRUE;
       
  1185 
       
  1186     /* unlink internal pad */
       
  1187     if (GST_PAD_IS_SRC (internal))
       
  1188       gst_pad_unlink (internal, oldtarget);
       
  1189     else
       
  1190       gst_pad_unlink (oldtarget, internal);
       
  1191 
       
  1192     GST_PROXY_PAD_RETARGET (internal) = FALSE;
  1085   }
  1193   }
  1086 
  1194 
  1087   result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
  1195   result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
  1088 
  1196 
  1089   if (result && newtarget) {
  1197   if (result && newtarget) {
       
  1198     if (GST_PAD_IS_SRC (newtarget)) {
       
  1199       g_signal_connect (newtarget, "notify::caps",
       
  1200           G_CALLBACK (on_src_target_notify), gpad);
       
  1201     }
       
  1202 
  1090     /* and link to internal pad */
  1203     /* and link to internal pad */
  1091     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
  1204     GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
  1092 
  1205 
  1093     if (GST_PAD_IS_SRC (internal))
  1206     if (GST_PAD_IS_SRC (internal))
  1094       lret = gst_pad_link (internal, newtarget);
  1207       lret = gst_pad_link (internal, newtarget);