gstreamer_core/plugins/elements/gstcapsfilter.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    20  * Boston, MA 02111-1307, USA.
    20  * Boston, MA 02111-1307, USA.
    21  */
    21  */
    22 /**
    22 /**
    23  * SECTION:element-capsfilter
    23  * SECTION:element-capsfilter
    24  *
    24  * @short_description: pass data though unmodified, but enforces format limmits
    25  * The element does not modify data as such, but can enforce limitations on the
    25  *
       
    26  * The element does not modify data as such, but can enforce limmitations on the
    26  * data format.
    27  * data format.
    27  */
    28  */
    28 
    29 
    29 #ifdef HAVE_CONFIG_H
    30 #ifdef HAVE_CONFIG_H
    30 #include "config.h"
    31 #include "config.h"
    33 #ifdef __SYMBIAN32__
    34 #ifdef __SYMBIAN32__
    34 #include <gst_global.h>
    35 #include <gst_global.h>
    35 #endif
    36 #endif
    36 #include "../../gst/gst-i18n-lib.h"
    37 #include "../../gst/gst-i18n-lib.h"
    37 #include "gstcapsfilter.h"
    38 #include "gstcapsfilter.h"
    38 #include <glib_global.h>
    39 
       
    40 #ifdef __SYMBIAN32__
       
    41 #include <gstelement.h>
       
    42 #endif
    39 enum
    43 enum
    40 {
    44 {
    41   PROP_0,
    45   PROP_0,
    42   PROP_FILTER_CAPS
    46   PROP_FILTER_CAPS
    43 };
    47 };
    68 static void gst_capsfilter_set_property (GObject * object, guint prop_id,
    72 static void gst_capsfilter_set_property (GObject * object, guint prop_id,
    69     const GValue * value, GParamSpec * pspec);
    73     const GValue * value, GParamSpec * pspec);
    70 static void gst_capsfilter_get_property (GObject * object, guint prop_id,
    74 static void gst_capsfilter_get_property (GObject * object, guint prop_id,
    71     GValue * value, GParamSpec * pspec);
    75     GValue * value, GParamSpec * pspec);
    72 static void gst_capsfilter_dispose (GObject * object);
    76 static void gst_capsfilter_dispose (GObject * object);
    73 
       
    74 static GstCaps *gst_capsfilter_transform_caps (GstBaseTransform * base,
    77 static GstCaps *gst_capsfilter_transform_caps (GstBaseTransform * base,
    75     GstPadDirection direction, GstCaps * caps);
    78     GstPadDirection direction, GstCaps * caps);
    76 static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
    79 static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
    77     GstBuffer * buf);
    80     GstBuffer * buf);
    78 static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans,
    81 static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans,
   110 
   113 
   111   g_object_class_install_property (gobject_class, PROP_FILTER_CAPS,
   114   g_object_class_install_property (gobject_class, PROP_FILTER_CAPS,
   112       g_param_spec_boxed ("caps", _("Filter caps"),
   115       g_param_spec_boxed ("caps", _("Filter caps"),
   113           _("Restrict the possible allowed capabilities (NULL means ANY). "
   116           _("Restrict the possible allowed capabilities (NULL means ANY). "
   114               "Setting this property takes a reference to the supplied GstCaps "
   117               "Setting this property takes a reference to the supplied GstCaps "
   115               "object."), GST_TYPE_CAPS,
   118               "object."), GST_TYPE_CAPS, G_PARAM_READWRITE));
   116           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   117 
   119 
   118   trans_class = GST_BASE_TRANSFORM_CLASS (klass);
   120   trans_class = GST_BASE_TRANSFORM_CLASS (klass);
   119   trans_class->transform_caps = gst_capsfilter_transform_caps;
   121   trans_class->transform_caps = gst_capsfilter_transform_caps;
   120   trans_class->transform_ip = gst_capsfilter_transform_ip;
   122   trans_class->transform_ip = gst_capsfilter_transform_ip;
   121   trans_class->prepare_output_buffer = gst_capsfilter_prepare_buf;
   123   trans_class->prepare_output_buffer = gst_capsfilter_prepare_buf;
   123 }
   125 }
   124 
   126 
   125 static void
   127 static void
   126 gst_capsfilter_init (GstCapsFilter * filter, GstCapsFilterClass * g_class)
   128 gst_capsfilter_init (GstCapsFilter * filter, GstCapsFilterClass * g_class)
   127 {
   129 {
   128   GstBaseTransform *trans = GST_BASE_TRANSFORM (filter);
       
   129   gst_base_transform_set_gap_aware (trans, TRUE);
       
   130   filter->filter_caps = gst_caps_new_any ();
   130   filter->filter_caps = gst_caps_new_any ();
   131 }
       
   132 
       
   133 static gboolean
       
   134 copy_func (GQuark field_id, const GValue * value, GstStructure * dest)
       
   135 {
       
   136   gst_structure_id_set_value (dest, field_id, value);
       
   137 
       
   138   return TRUE;
       
   139 }
   131 }
   140 
   132 
   141 static void
   133 static void
   142 gst_capsfilter_set_property (GObject * object, guint prop_id,
   134 gst_capsfilter_set_property (GObject * object, guint prop_id,
   143     const GValue * value, GParamSpec * pspec)
   135     const GValue * value, GParamSpec * pspec)
   145   GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
   137   GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
   146 
   138 
   147   switch (prop_id) {
   139   switch (prop_id) {
   148     case PROP_FILTER_CAPS:{
   140     case PROP_FILTER_CAPS:{
   149       GstCaps *new_caps;
   141       GstCaps *new_caps;
   150       GstCaps *old_caps, *suggest, *nego;
   142       GstCaps *old_caps;
   151       const GstCaps *new_caps_val = gst_value_get_caps (value);
   143       const GstCaps *new_caps_val = gst_value_get_caps (value);
   152 
   144 
   153       if (new_caps_val == NULL) {
   145       if (new_caps_val == NULL) {
   154         new_caps = gst_caps_new_any ();
   146         new_caps = gst_caps_new_any ();
   155       } else {
   147       } else {
   156         new_caps = (GstCaps *) new_caps_val;
   148         new_caps = (GstCaps *) new_caps_val;
   157         gst_caps_ref (new_caps);
   149         gst_caps_ref (new_caps);
   158       }
   150       }
   159 
   151 
   160       GST_OBJECT_LOCK (capsfilter);
       
   161       old_caps = capsfilter->filter_caps;
   152       old_caps = capsfilter->filter_caps;
   162       capsfilter->filter_caps = new_caps;
   153       capsfilter->filter_caps = new_caps;
   163       GST_OBJECT_UNLOCK (capsfilter);
       
   164 
       
   165       gst_caps_unref (old_caps);
   154       gst_caps_unref (old_caps);
   166 
   155 
   167       GST_DEBUG_OBJECT (capsfilter, "set new caps %" GST_PTR_FORMAT, new_caps);
   156       GST_DEBUG_OBJECT (capsfilter, "set new caps %" GST_PTR_FORMAT, new_caps);
   168 
   157 
   169       /* filter the currently negotiated format against the new caps */
   158       /* FIXME: Need to activate these caps on the pads
   170       GST_OBJECT_LOCK (GST_BASE_TRANSFORM_SINK_PAD (object));
   159        * http://bugzilla.gnome.org/show_bug.cgi?id=361718
   171       nego = GST_PAD_CAPS (GST_BASE_TRANSFORM_SINK_PAD (object));
   160        */
   172       if (nego) {
       
   173         GST_DEBUG_OBJECT (capsfilter, "we had negotiated caps %" GST_PTR_FORMAT,
       
   174             nego);
       
   175 
       
   176         if (G_UNLIKELY (gst_caps_is_any (new_caps))) {
       
   177           GST_DEBUG_OBJECT (capsfilter, "not settings any suggestion");
       
   178 
       
   179           suggest = NULL;
       
   180         } else {
       
   181           GstStructure *s1, *s2;
       
   182 
       
   183           /* first check if the name is the same */
       
   184           s1 = gst_caps_get_structure (nego, 0);
       
   185           s2 = gst_caps_get_structure (new_caps, 0);
       
   186 
       
   187           if (gst_structure_get_name_id (s1) == gst_structure_get_name_id (s2)) {
       
   188             /* same name, copy all fields from the new caps into the previously
       
   189              * negotiated caps */
       
   190             suggest = gst_caps_copy (nego);
       
   191             s1 = gst_caps_get_structure (suggest, 0);
       
   192             gst_structure_foreach (s2, (GstStructureForeachFunc) copy_func, s1);
       
   193             GST_DEBUG_OBJECT (capsfilter, "copied structure fields");
       
   194           } else {
       
   195             GST_DEBUG_OBJECT (capsfilter, "different structure names");
       
   196             /* different names, we can only suggest the complete caps */
       
   197             suggest = gst_caps_copy (new_caps);
       
   198           }
       
   199         }
       
   200       } else {
       
   201         GST_DEBUG_OBJECT (capsfilter, "no negotiated caps");
       
   202         /* no previous caps, the getcaps function will be used to find suitable
       
   203          * caps */
       
   204         suggest = NULL;
       
   205       }
       
   206       GST_OBJECT_UNLOCK (GST_BASE_TRANSFORM_SINK_PAD (object));
       
   207 
       
   208       GST_DEBUG_OBJECT (capsfilter, "suggesting new caps %" GST_PTR_FORMAT,
       
   209           suggest);
       
   210       gst_base_transform_suggest (GST_BASE_TRANSFORM (object), suggest, 0);
       
   211       if (suggest)
       
   212         gst_caps_unref (suggest);
       
   213 
       
   214       break;
   161       break;
   215     }
   162     }
   216     default:
   163     default:
   217       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   164       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   218       break;
   165       break;
   225 {
   172 {
   226   GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
   173   GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
   227 
   174 
   228   switch (prop_id) {
   175   switch (prop_id) {
   229     case PROP_FILTER_CAPS:
   176     case PROP_FILTER_CAPS:
   230       GST_OBJECT_LOCK (capsfilter);
       
   231       gst_value_set_caps (value, capsfilter->filter_caps);
   177       gst_value_set_caps (value, capsfilter->filter_caps);
   232       GST_OBJECT_UNLOCK (capsfilter);
       
   233       break;
   178       break;
   234     default:
   179     default:
   235       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   180       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   236       break;
   181       break;
   237   }
   182   }
   250 static GstCaps *
   195 static GstCaps *
   251 gst_capsfilter_transform_caps (GstBaseTransform * base,
   196 gst_capsfilter_transform_caps (GstBaseTransform * base,
   252     GstPadDirection direction, GstCaps * caps)
   197     GstPadDirection direction, GstCaps * caps)
   253 {
   198 {
   254   GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
   199   GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
   255   GstCaps *ret, *filter_caps;
   200   GstCaps *ret;
   256 
   201 
   257   GST_OBJECT_LOCK (capsfilter);
   202   ret = gst_caps_intersect (caps, capsfilter->filter_caps);
   258   filter_caps = gst_caps_ref (capsfilter->filter_caps);
       
   259   GST_OBJECT_UNLOCK (capsfilter);
       
   260 
       
   261   ret = gst_caps_intersect (caps, filter_caps);
       
   262   GST_DEBUG_OBJECT (capsfilter, "input:     %" GST_PTR_FORMAT, caps);
       
   263   GST_DEBUG_OBJECT (capsfilter, "filter:    %" GST_PTR_FORMAT, filter_caps);
       
   264   GST_DEBUG_OBJECT (capsfilter, "intersect: %" GST_PTR_FORMAT, ret);
       
   265 
       
   266   gst_caps_unref (filter_caps);
       
   267 
   203 
   268   return ret;
   204   return ret;
   269 }
   205 }
   270 
   206 
   271 static gboolean
   207 static gboolean
   299  */
   235  */
   300 static GstFlowReturn
   236 static GstFlowReturn
   301 gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
   237 gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
   302     gint size, GstCaps * caps, GstBuffer ** buf)
   238     gint size, GstCaps * caps, GstBuffer ** buf)
   303 {
   239 {
   304   GstFlowReturn ret = GST_FLOW_OK;
       
   305 
       
   306   if (GST_BUFFER_CAPS (input) != NULL) {
   240   if (GST_BUFFER_CAPS (input) != NULL) {
   307     /* Output buffer already has caps */
   241     /* Output buffer already has caps */
   308     GST_LOG_OBJECT (trans, "Input buffer already has caps (implicitely fixed)");
   242     GST_DEBUG_OBJECT (trans,
       
   243         "Input buffer already has caps (implicitely fixed)");
   309     /* FIXME : Move this behaviour to basetransform. The given caps are the ones
   244     /* FIXME : Move this behaviour to basetransform. The given caps are the ones
   310      * of the source pad, therefore our outgoing buffers should always have
   245      * of the source pad, therefore our outgoing buffers should always have
   311      * those caps. */
   246      * those caps. */
   312     gst_buffer_set_caps (input, caps);
   247     gst_buffer_set_caps (input, caps);
   313     gst_buffer_ref (input);
   248     gst_buffer_ref (input);
   341       GST_BUFFER_CAPS (*buf) = out_caps;
   276       GST_BUFFER_CAPS (*buf) = out_caps;
   342 
   277 
   343       if (GST_PAD_CAPS (trans->srcpad) == NULL)
   278       if (GST_PAD_CAPS (trans->srcpad) == NULL)
   344         gst_pad_set_caps (trans->srcpad, out_caps);
   279         gst_pad_set_caps (trans->srcpad, out_caps);
   345     } else {
   280     } else {
   346       gchar *caps_str = gst_caps_to_string (out_caps);
   281       GST_DEBUG_OBJECT (trans, "Have unfixed output caps %" GST_PTR_FORMAT,
   347 
   282           out_caps);
   348       GST_DEBUG_OBJECT (trans, "Cannot choose caps. Have unfixed output caps %"
       
   349           GST_PTR_FORMAT, out_caps);
       
   350       gst_caps_unref (out_caps);
   283       gst_caps_unref (out_caps);
   351 
       
   352       ret = GST_FLOW_ERROR;
       
   353       GST_ELEMENT_ERROR (trans, STREAM, FORMAT,
       
   354           ("Filter caps do not completely specify the output format"),
       
   355           ("Output caps are unfixed: %s", caps_str));
       
   356       g_free (caps_str);
       
   357     }
   284     }
   358   }
   285   }
   359 
   286 
   360   return ret;
   287   return GST_FLOW_OK;
   361 }
   288 }