gstreamer_core/plugins/elements/gstcapsfilter.c
branchRCL_3
changeset 29 567bb019e3e3
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
6:9b2c3c7a1a9c 29:567bb019e3e3
    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  * @short_description: pass data though unmodified, but enforces format limmits
       
    25  *
    24  *
    26  * The element does not modify data as such, but can enforce limmitations on the
    25  * The element does not modify data as such, but can enforce limitations on the
    27  * data format.
    26  * data format.
    28  */
    27  */
    29 
    28 
    30 #ifdef HAVE_CONFIG_H
    29 #ifdef HAVE_CONFIG_H
    31 #include "config.h"
    30 #include "config.h"
    34 #ifdef __SYMBIAN32__
    33 #ifdef __SYMBIAN32__
    35 #include <gst_global.h>
    34 #include <gst_global.h>
    36 #endif
    35 #endif
    37 #include "../../gst/gst-i18n-lib.h"
    36 #include "../../gst/gst-i18n-lib.h"
    38 #include "gstcapsfilter.h"
    37 #include "gstcapsfilter.h"
    39 
    38 #include <glib_global.h>
    40 #ifdef __SYMBIAN32__
       
    41 #include <gstelement.h>
       
    42 #endif
       
    43 enum
    39 enum
    44 {
    40 {
    45   PROP_0,
    41   PROP_0,
    46   PROP_FILTER_CAPS
    42   PROP_FILTER_CAPS
    47 };
    43 };
    72 static void gst_capsfilter_set_property (GObject * object, guint prop_id,
    68 static void gst_capsfilter_set_property (GObject * object, guint prop_id,
    73     const GValue * value, GParamSpec * pspec);
    69     const GValue * value, GParamSpec * pspec);
    74 static void gst_capsfilter_get_property (GObject * object, guint prop_id,
    70 static void gst_capsfilter_get_property (GObject * object, guint prop_id,
    75     GValue * value, GParamSpec * pspec);
    71     GValue * value, GParamSpec * pspec);
    76 static void gst_capsfilter_dispose (GObject * object);
    72 static void gst_capsfilter_dispose (GObject * object);
       
    73 
    77 static GstCaps *gst_capsfilter_transform_caps (GstBaseTransform * base,
    74 static GstCaps *gst_capsfilter_transform_caps (GstBaseTransform * base,
    78     GstPadDirection direction, GstCaps * caps);
    75     GstPadDirection direction, GstCaps * caps);
    79 static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
    76 static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
    80     GstBuffer * buf);
    77     GstBuffer * buf);
    81 static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans,
    78 static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans,
   113 
   110 
   114   g_object_class_install_property (gobject_class, PROP_FILTER_CAPS,
   111   g_object_class_install_property (gobject_class, PROP_FILTER_CAPS,
   115       g_param_spec_boxed ("caps", _("Filter caps"),
   112       g_param_spec_boxed ("caps", _("Filter caps"),
   116           _("Restrict the possible allowed capabilities (NULL means ANY). "
   113           _("Restrict the possible allowed capabilities (NULL means ANY). "
   117               "Setting this property takes a reference to the supplied GstCaps "
   114               "Setting this property takes a reference to the supplied GstCaps "
   118               "object."), GST_TYPE_CAPS, G_PARAM_READWRITE));
   115               "object."), GST_TYPE_CAPS,
       
   116           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   119 
   117 
   120   trans_class = GST_BASE_TRANSFORM_CLASS (klass);
   118   trans_class = GST_BASE_TRANSFORM_CLASS (klass);
   121   trans_class->transform_caps = gst_capsfilter_transform_caps;
   119   trans_class->transform_caps = gst_capsfilter_transform_caps;
   122   trans_class->transform_ip = gst_capsfilter_transform_ip;
   120   trans_class->transform_ip = gst_capsfilter_transform_ip;
   123   trans_class->prepare_output_buffer = gst_capsfilter_prepare_buf;
   121   trans_class->prepare_output_buffer = gst_capsfilter_prepare_buf;
   125 }
   123 }
   126 
   124 
   127 static void
   125 static void
   128 gst_capsfilter_init (GstCapsFilter * filter, GstCapsFilterClass * g_class)
   126 gst_capsfilter_init (GstCapsFilter * filter, GstCapsFilterClass * g_class)
   129 {
   127 {
       
   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;
   131 }
   139 }
   132 
   140 
   133 static void
   141 static void
   134 gst_capsfilter_set_property (GObject * object, guint prop_id,
   142 gst_capsfilter_set_property (GObject * object, guint prop_id,
   135     const GValue * value, GParamSpec * pspec)
   143     const GValue * value, GParamSpec * pspec)
   137   GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
   145   GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
   138 
   146 
   139   switch (prop_id) {
   147   switch (prop_id) {
   140     case PROP_FILTER_CAPS:{
   148     case PROP_FILTER_CAPS:{
   141       GstCaps *new_caps;
   149       GstCaps *new_caps;
   142       GstCaps *old_caps;
   150       GstCaps *old_caps, *suggest, *nego;
   143       const GstCaps *new_caps_val = gst_value_get_caps (value);
   151       const GstCaps *new_caps_val = gst_value_get_caps (value);
   144 
   152 
   145       if (new_caps_val == NULL) {
   153       if (new_caps_val == NULL) {
   146         new_caps = gst_caps_new_any ();
   154         new_caps = gst_caps_new_any ();
   147       } else {
   155       } else {
   148         new_caps = (GstCaps *) new_caps_val;
   156         new_caps = (GstCaps *) new_caps_val;
   149         gst_caps_ref (new_caps);
   157         gst_caps_ref (new_caps);
   150       }
   158       }
   151 
   159 
       
   160       GST_OBJECT_LOCK (capsfilter);
   152       old_caps = capsfilter->filter_caps;
   161       old_caps = capsfilter->filter_caps;
   153       capsfilter->filter_caps = new_caps;
   162       capsfilter->filter_caps = new_caps;
       
   163       GST_OBJECT_UNLOCK (capsfilter);
       
   164 
   154       gst_caps_unref (old_caps);
   165       gst_caps_unref (old_caps);
   155 
   166 
   156       GST_DEBUG_OBJECT (capsfilter, "set new caps %" GST_PTR_FORMAT, new_caps);
   167       GST_DEBUG_OBJECT (capsfilter, "set new caps %" GST_PTR_FORMAT, new_caps);
   157 
   168 
   158       /* FIXME: Need to activate these caps on the pads
   169       /* filter the currently negotiated format against the new caps */
   159        * http://bugzilla.gnome.org/show_bug.cgi?id=361718
   170       GST_OBJECT_LOCK (GST_BASE_TRANSFORM_SINK_PAD (object));
   160        */
   171       nego = GST_PAD_CAPS (GST_BASE_TRANSFORM_SINK_PAD (object));
       
   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 
   161       break;
   214       break;
   162     }
   215     }
   163     default:
   216     default:
   164       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   217       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   165       break;
   218       break;
   172 {
   225 {
   173   GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
   226   GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
   174 
   227 
   175   switch (prop_id) {
   228   switch (prop_id) {
   176     case PROP_FILTER_CAPS:
   229     case PROP_FILTER_CAPS:
       
   230       GST_OBJECT_LOCK (capsfilter);
   177       gst_value_set_caps (value, capsfilter->filter_caps);
   231       gst_value_set_caps (value, capsfilter->filter_caps);
       
   232       GST_OBJECT_UNLOCK (capsfilter);
   178       break;
   233       break;
   179     default:
   234     default:
   180       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   235       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   181       break;
   236       break;
   182   }
   237   }
   195 static GstCaps *
   250 static GstCaps *
   196 gst_capsfilter_transform_caps (GstBaseTransform * base,
   251 gst_capsfilter_transform_caps (GstBaseTransform * base,
   197     GstPadDirection direction, GstCaps * caps)
   252     GstPadDirection direction, GstCaps * caps)
   198 {
   253 {
   199   GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
   254   GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
   200   GstCaps *ret;
   255   GstCaps *ret, *filter_caps;
   201 
   256 
   202   ret = gst_caps_intersect (caps, capsfilter->filter_caps);
   257   GST_OBJECT_LOCK (capsfilter);
       
   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);
   203 
   267 
   204   return ret;
   268   return ret;
   205 }
   269 }
   206 
   270 
   207 static gboolean
   271 static gboolean
   235  */
   299  */
   236 static GstFlowReturn
   300 static GstFlowReturn
   237 gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
   301 gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
   238     gint size, GstCaps * caps, GstBuffer ** buf)
   302     gint size, GstCaps * caps, GstBuffer ** buf)
   239 {
   303 {
       
   304   GstFlowReturn ret = GST_FLOW_OK;
       
   305 
   240   if (GST_BUFFER_CAPS (input) != NULL) {
   306   if (GST_BUFFER_CAPS (input) != NULL) {
   241     /* Output buffer already has caps */
   307     /* Output buffer already has caps */
   242     GST_DEBUG_OBJECT (trans,
   308     GST_LOG_OBJECT (trans, "Input buffer already has caps (implicitely fixed)");
   243         "Input buffer already has caps (implicitely fixed)");
       
   244     /* FIXME : Move this behaviour to basetransform. The given caps are the ones
   309     /* FIXME : Move this behaviour to basetransform. The given caps are the ones
   245      * of the source pad, therefore our outgoing buffers should always have
   310      * of the source pad, therefore our outgoing buffers should always have
   246      * those caps. */
   311      * those caps. */
   247     gst_buffer_set_caps (input, caps);
   312     gst_buffer_set_caps (input, caps);
   248     gst_buffer_ref (input);
   313     gst_buffer_ref (input);
   276       GST_BUFFER_CAPS (*buf) = out_caps;
   341       GST_BUFFER_CAPS (*buf) = out_caps;
   277 
   342 
   278       if (GST_PAD_CAPS (trans->srcpad) == NULL)
   343       if (GST_PAD_CAPS (trans->srcpad) == NULL)
   279         gst_pad_set_caps (trans->srcpad, out_caps);
   344         gst_pad_set_caps (trans->srcpad, out_caps);
   280     } else {
   345     } else {
   281       GST_DEBUG_OBJECT (trans, "Have unfixed output caps %" GST_PTR_FORMAT,
   346       gchar *caps_str = gst_caps_to_string (out_caps);
   282           out_caps);
   347 
       
   348       GST_DEBUG_OBJECT (trans, "Cannot choose caps. Have unfixed output caps %"
       
   349           GST_PTR_FORMAT, out_caps);
   283       gst_caps_unref (out_caps);
   350       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);
   284     }
   357     }
   285   }
   358   }
   286 
   359 
   287   return GST_FLOW_OK;
   360   return ret;
   288 }
   361 }