static void check_caps (const gchar * set, const gchar * subset) { GstCaps *one, *two, *test, *test2; g_print (" A = %s\n", set); one = gst_caps_from_string (set); g_print (" B = %s\n", subset); two = gst_caps_from_string (subset); /* basics */ test = gst_caps_subtract (one, one); g_assert (gst_caps_is_empty (test)); gst_caps_unref (test); test = gst_caps_subtract (two, two); g_assert (gst_caps_is_empty (test)); gst_caps_unref (test); test = gst_caps_subtract (two, one); g_assert (gst_caps_is_empty (test)); gst_caps_unref (test); /* now the nice part */ test = gst_caps_subtract (one, two); g_assert (!gst_caps_is_empty (test)); g_print (" A - B = %s\n", gst_caps_to_string (test)); test2 = gst_caps_union (test, two); g_print ("A - B + B = %s\n", gst_caps_to_string (test2)); gst_caps_unref (test); test = gst_caps_subtract (test2, one); g_assert (gst_caps_is_empty (test)); gst_caps_unref (test); }
CapsPtr Caps::getUnion(const CapsPtr & caps2) const { return CapsPtr::wrap(gst_caps_union(object<GstCaps>(), caps2), false); }
/* if element caps already in list, will make sure Transform elements have * priority and replace old ones */ static GList * create_codec_cap_list (GstElementFactory *factory, GstPadDirection direction, GList *list, GstCaps *rtp_caps) { const GList *pads = factory->staticpadtemplates; gint i; /* Let us look at each pad for stuff to add*/ while (pads) { GstCaps *caps = NULL; GstStaticPadTemplate *padtemplate = NULL; padtemplate = (GstStaticPadTemplate *) (pads->data); pads = g_list_next (pads); if (padtemplate->direction != direction) continue; if (GST_PAD_TEMPLATE_PRESENCE (padtemplate) != GST_PAD_ALWAYS) { continue; } caps = gst_static_caps_get (&padtemplate->static_caps); /* DEBUG ("%s caps are %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)), gst_caps_to_string (caps)); */ /* skips caps ANY */ if (!caps || gst_caps_is_any (caps)) { goto done; } /* let us add one entry to the list per media type */ for (i = 0; i < gst_caps_get_size (caps); i++) { CodecCap *entry = NULL; GList *found_item = NULL; GstStructure *structure = gst_caps_get_structure (caps, i); GstCaps *cur_caps = gst_caps_new_full (gst_structure_copy (structure), NULL); /* FIXME fix this in gstreamer! The rtpdepay element is bogus, it claims to * be a depayloader yet has application/x-rtp on both sides and does * absolutely nothing */ /* Let's check if media caps are really media caps, this is to deal with * wierd elements such as rtpdepay that says it's a depayloader but has * application/x-rtp on src and sink pads */ const gchar *name = gst_structure_get_name (structure); if (g_ascii_strcasecmp (name, "application/x-rtp") == 0) { GST_DEBUG ("skipping %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); continue; } /* let's check if this caps is already in the list, if so let's replace * that CodecCap list instead of creating a new one */ /* we need to compare both media caps and rtp caps */ found_item = g_list_find_custom (list, cur_caps, (GCompareFunc)compare_media_caps); if (found_item) { entry = (CodecCap *)found_item->data; /* if RTP caps exist and don't match nullify entry */ if (rtp_caps && compare_rtp_caps (found_item->data, rtp_caps)) { entry = NULL; } } if (!entry) { entry = g_slice_new0 (CodecCap); entry->caps = cur_caps; if (rtp_caps) { entry->rtp_caps = rtp_caps; gst_caps_ref (rtp_caps); } list = g_list_append (list, entry); entry->element_list1 = g_list_prepend (NULL, g_list_prepend (NULL, factory)); gst_object_ref (factory); } else { GstCaps *newcaps; entry->element_list1->data = g_list_append (entry->element_list1->data, factory); gst_object_ref (factory); if (rtp_caps) { if (entry->rtp_caps) { GstCaps *new_rtp_caps; new_rtp_caps = gst_caps_union (rtp_caps, entry->rtp_caps); gst_caps_unref (entry->rtp_caps); entry->rtp_caps = new_rtp_caps; } else { entry->rtp_caps = rtp_caps; /* This shouldn't happen, its we're looking at rtp elements * or we're not */ g_assert_not_reached (); } gst_caps_unref (rtp_caps); } newcaps = gst_caps_union (cur_caps, entry->caps); gst_caps_unref (entry->caps); gst_caps_unref (cur_caps); entry->caps = newcaps; } } done: if (caps != NULL) { gst_caps_unref (caps); } } return list; }
/* returns the intersection of two lists */ static GList * codec_cap_list_intersect (GList *list1, GList *list2) { GList *walk1, *walk2; CodecCap *codec_cap1, *codec_cap2; GstCaps *caps1, *caps2; GstCaps *rtp_caps1, *rtp_caps2; GList *intersection_list = NULL; for (walk1 = g_list_first (list1); walk1; walk1 = g_list_next (walk1)) { CodecCap *item = NULL; codec_cap1 = (CodecCap *)(walk1->data); caps1 = codec_cap1->caps; rtp_caps1 = codec_cap1->rtp_caps; for (walk2 = list2; walk2; walk2 = g_list_next (walk2)) { GstCaps *intersection = NULL; GstCaps *rtp_intersection = NULL; codec_cap2 = (CodecCap *)(walk2->data); caps2 = codec_cap2->caps; rtp_caps2 = codec_cap2->rtp_caps; //g_debug ("intersecting %s AND %s", gst_caps_to_string (caps1), gst_caps_to_string (caps2)); intersection = gst_caps_intersect (caps1, caps2); if (rtp_caps1 && rtp_caps2) { //g_debug ("RTP intersecting %s AND %s", gst_caps_to_string (rtp_caps1), gst_caps_to_string (rtp_caps2)); rtp_intersection = gst_caps_intersect (rtp_caps1, rtp_caps2); } if (!gst_caps_is_empty (intersection) && (rtp_intersection == NULL || !gst_caps_is_empty (rtp_intersection))) { if (item) { GstCaps *new_caps = gst_caps_union (item->caps, intersection); GList *tmplist; gst_caps_unref (item->caps); item->caps = new_caps; for (tmplist = g_list_first (codec_cap2->element_list1->data); tmplist; tmplist = g_list_next (tmplist)) { if (g_list_index (item->element_list2->data, tmplist->data) < 0) { item->element_list2->data = g_list_concat ( item->element_list2->data, g_list_copy (codec_cap2->element_list1->data)); g_list_foreach (codec_cap2->element_list1->data, (GFunc) gst_object_ref, NULL); } } } else { item = g_slice_new0 (CodecCap); item->caps = gst_caps_ref (intersection); if (rtp_caps1 && rtp_caps2) { item->rtp_caps = rtp_intersection; } else if (rtp_caps1) { item->rtp_caps = rtp_caps1; gst_caps_ref (rtp_caps1); } else if (rtp_caps2) { item->rtp_caps = rtp_caps2; gst_caps_ref (rtp_caps2); } /* during an intersect, we concat/copy previous lists together and put them * into 1 and 2 */ item->element_list1 = g_list_concat ( copy_element_list (codec_cap1->element_list1), copy_element_list (codec_cap1->element_list2)); item->element_list2 = g_list_concat ( copy_element_list (codec_cap2->element_list1), copy_element_list (codec_cap2->element_list2)); intersection_list = g_list_append (intersection_list, item); if (rtp_intersection) break; } } else { if (rtp_intersection) gst_caps_unref (rtp_intersection); } gst_caps_unref (intersection); } } return intersection_list; }
/* * Method: union(caps) * caps: another Gst::Caps. * * Creates a new Gst::Caps that contains all the formats that are in either * self and the given caps. * * Returns: a new Gst::Caps object. */ static VALUE rg_union (VALUE self, VALUE caps) { return RGST_CAPS_NEW (gst_caps_union (RGST_CAPS (self), RGST_CAPS (caps))); }