+2005-08-16 Wim Taymans <wim@fluendo.com>
+
+ * check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite):
+ Added subtract checks.
+
+ * docs/design/part-events.txt:
+ Some more docs about newsegment
+
+ * gst/gstbin.c: (gst_bin_change_state), (bin_bus_handler):
+ Fix FIXME
+
+ * gst/gstcaps.c: (gst_caps_to_string):
+ Add comments, cleanups.
+
+ * gst/gstelement.c: (gst_element_save_thyself):
+ cleanups
+
+ * gst/gstvalue.c: (gst_value_collect_int_range),
+ (gst_string_unwrap), (gst_value_union_int_int_range),
+ (gst_value_union_int_range_int_range),
+ (gst_value_intersect_int_int_range),
+ (gst_value_intersect_int_range_int_range),
+ (gst_value_intersect_double_double_range),
+ (gst_value_intersect_double_range_double_range),
+ (gst_value_intersect_list), (gst_value_subtract_int_int_range),
+ (gst_value_subtract_int_range_int),
+ (gst_value_subtract_double_range_double),
+ (gst_value_subtract_double_range_double_range),
+ (gst_value_subtract_from_list), (gst_value_subtract_list),
+ (gst_value_can_compare), (gst_value_compare_fraction):
+ Cleanups, add comments, remove unneeded asserts.
+
2005-08-15 Thomas Vander Stichele <thomas at apestaart dot org>
* tools/gst-launch.c: (event_loop):
g_value_init (&src1, G_TYPE_INT);
g_value_set_int (&src1, 10);
g_value_init (&src2, G_TYPE_INT);
- g_value_set_int (&src1, 20);
+ g_value_set_int (&src2, 20);
ret = gst_value_intersect (&dest, &src1, &src2);
- fail_unless (ret == 0);
+ fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
GST_END_TEST;
+
+GST_START_TEST (test_value_subtract_int)
+{
+ GValue dest = { 0 };
+ GValue src1 = { 0 };
+ GValue src2 = { 0 };
+ const GValue *tmp;
+ gboolean ret;
+
+ /* int <-> int
+ */
+ g_value_init (&src1, G_TYPE_INT);
+ g_value_set_int (&src1, 10);
+ g_value_init (&src2, G_TYPE_INT);
+ g_value_set_int (&src2, 20);
+ /* subtract as in sets, result is 10 */
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
+ g_value_unset (&dest);
+
+ /* same values, yields empty set */
+ ret = gst_value_subtract (&dest, &src1, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* int <-> int_range
+ */
+
+ /* would yield an empty set */
+ g_value_init (&src1, G_TYPE_INT);
+ g_value_set_int (&src1, 10);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 0, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, should create a list of two ranges. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 0);
+ fail_unless (gst_value_get_int_range_max (tmp) == 9);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 11);
+ fail_unless (gst_value_get_int_range_max (tmp) == 20);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* border case 1, empty set */
+ g_value_init (&src1, G_TYPE_INT);
+ g_value_set_int (&src1, 10);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 10, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, should create a new range. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 11);
+ fail_unless (gst_value_get_int_range_max (&dest) == 20);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* border case 2, empty set */
+ g_value_init (&src1, G_TYPE_INT);
+ g_value_set_int (&src1, 20);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 10, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, should create a new range. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 10);
+ fail_unless (gst_value_get_int_range_max (&dest) == 19);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* case 3, valid set */
+ g_value_init (&src1, G_TYPE_INT);
+ g_value_set_int (&src1, 0);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 10, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (G_VALUE_HOLDS_INT (&dest) == TRUE);
+ fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
+ g_value_unset (&dest);
+
+ /* and the other way around, should keep the range. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 10);
+ fail_unless (gst_value_get_int_range_max (&dest) == 20);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* int_range <-> int_range
+ */
+
+ /* same range, empty set */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 20);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 10, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* non overlapping ranges */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 20);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 30, 40);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 10);
+ fail_unless (gst_value_get_int_range_max (&dest) == 20);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 30);
+ fail_unless (gst_value_get_int_range_max (&dest) == 40);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* completely overlapping ranges */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 20);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 10, 30);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 21);
+ fail_unless (gst_value_get_int_range_max (&dest) == 30);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* partially overlapping ranges */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 20);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 15, 30);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 10);
+ fail_unless (gst_value_get_int_range_max (&dest) == 14);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 21);
+ fail_unless (gst_value_get_int_range_max (&dest) == 30);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* create a hole { int_range, int_range } */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 30);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 15, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 10);
+ fail_unless (gst_value_get_int_range_max (tmp) == 14);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 21);
+ fail_unless (gst_value_get_int_range_max (tmp) == 30);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* create a hole, { int, int } */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 30);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 11, 29);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
+ fail_unless (g_value_get_int (tmp) == 10);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
+ fail_unless (g_value_get_int (tmp) == 30);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* create a hole, { int, int_range } */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 30);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 11, 28);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
+ fail_unless (g_value_get_int (tmp) == 10);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 29);
+ fail_unless (gst_value_get_int_range_max (tmp) == 30);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* create a hole, { int_range, int } */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 30);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 12, 29);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 10);
+ fail_unless (gst_value_get_int_range_max (tmp) == 11);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
+ fail_unless (g_value_get_int (tmp) == 30);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_value_subtract_double)
+{
+ GValue dest = { 0 };
+ GValue src1 = { 0 };
+ GValue src2 = { 0 };
+ const GValue *tmp;
+ gboolean ret;
+
+ /* double <-> double
+ */
+ g_value_init (&src1, G_TYPE_DOUBLE);
+ g_value_set_double (&src1, 10.0);
+ g_value_init (&src2, G_TYPE_DOUBLE);
+ g_value_set_double (&src2, 20.0);
+ /* subtract as in sets, result is 10 */
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
+ g_value_unset (&dest);
+
+ /* same values, yields empty set */
+ ret = gst_value_subtract (&dest, &src1, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* double <-> double_range
+ */
+
+ /* would yield an empty set */
+ g_value_init (&src1, G_TYPE_DOUBLE);
+ g_value_set_double (&src1, 10.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 0.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, we cannot create open ranges
+ * so the result is the range again */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 0.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* border case 1, empty set */
+ g_value_init (&src1, G_TYPE_DOUBLE);
+ g_value_set_double (&src1, 10.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 10.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, should keep same range as
+ * we don't have open ranges. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* border case 2, empty set */
+ g_value_init (&src1, G_TYPE_DOUBLE);
+ g_value_set_double (&src1, 20.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 10.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, should keep same range as
+ * we don't have open ranges. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* case 3, valid set */
+ g_value_init (&src1, G_TYPE_DOUBLE);
+ g_value_set_double (&src1, 0.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 10.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (G_VALUE_HOLDS_DOUBLE (&dest) == TRUE);
+ fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
+ g_value_unset (&dest);
+
+ /* and the other way around, should keep the range. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* double_range <-> double_range
+ */
+
+ /* same range, empty set */
+ g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src1, 10.0, 20.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 10.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* non overlapping ranges */
+ g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src1, 10.0, 20.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 30.0, 40.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 30.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 40.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* completely overlapping ranges */
+ g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src1, 10.0, 20.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 10.0, 30.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 20.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 30.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* partially overlapping ranges */
+ g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src1, 10.0, 20.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 15.0, 30.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 15.0);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 20.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 30.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* create a hole { double_range, double_range } */
+ g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src1, 10.0, 30.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 15.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_double_range_min (tmp) == 10.0);
+ fail_unless (gst_value_get_double_range_max (tmp) == 15.0);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_double_range_min (tmp) == 20.0);
+ fail_unless (gst_value_get_double_range_max (tmp) == 30.0);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+}
+
+GST_END_TEST;
+
Suite *
gst_value_suite (void)
{
tcase_add_test (tc_chain, test_deserialize_string);
tcase_add_test (tc_chain, test_value_compare);
tcase_add_test (tc_chain, test_value_intersect);
+ tcase_add_test (tc_chain, test_value_subtract_int);
+ tcase_add_test (tc_chain, test_value_subtract_double);
+
return s;
}
start and stop values. Sinks are allowed to drop buffers with timestamps out
of the indicated newsegment range.
+If a newsegment arrives at an element not preceeded by a flush event, the
+streamtime of the pipeline will not be reset to 0 so any element that syncs
+to the clock must use the stop times of the previous newsegment events to
+make the buffer timestamps increasing.
+
SEEK
----
GST_LOCK (bin);
if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
- /* FIXME: we reffed some children already, are we leaking refcounts
- * in that case ? */
GST_INFO_OBJECT (bin, "bin->children_cookie changed, restarting");
+ /* restart will unref the children in the queues so that we don't
+ * leak refcounts. */
goto restart;
}
children = g_list_next (children);
return res;
}
-/* FIXME, make me threadsafe */
static GstBusSyncReply
bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
{
GST_DEBUG_OBJECT (bin, "[msg %p] handling child message of type %d",
message, GST_MESSAGE_TYPE (message));
- /* we don't want messages from the streaming thread while we're doing the
- * state change. We do want them from the state change functions. */
+
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_EOS:{
gchar *name = gst_object_get_name (GST_MESSAGE_SRC (message));
GST_DEBUG_OBJECT (bin, "got EOS message from %s", name);
g_free (name);
+ /* collect all eos messages from the children */
GST_LOCK (bin->child_bus);
bin->eosed = g_list_prepend (bin->eosed, GST_MESSAGE_SRC (message));
GST_UNLOCK (bin->child_bus);
+ /* if we are completely EOS, we forward an EOS message */
if (is_eos (bin)) {
GST_DEBUG_OBJECT (bin, "all sinks posted EOS");
gst_element_post_message (GST_ELEMENT (bin),
gst_caps_to_string (const GstCaps * caps)
{
int i;
- GstStructure *structure;
GString *s;
- char *sstr;
/* NOTE: This function is potentially called by the debug system,
* so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.)
* called by gst_caps_to_string. In particular, calls should
* not use the GST_PTR_FORMAT extension. */
- /* FIXME does this leak? */
-
if (caps == NULL) {
return g_strdup ("NULL");
}
if (gst_caps_is_empty (caps)) {
return g_strdup ("EMPTY");
}
+
s = g_string_new ("");
- structure = gst_caps_get_structure (caps, 0);
- sstr = gst_structure_to_string (structure);
- g_string_append (s, sstr);
- g_free (sstr);
+ for (i = 0; i < caps->structs->len; i++) {
+ GstStructure *structure;
+ char *sstr;
- for (i = 1; i < caps->structs->len; i++) {
- structure = gst_caps_get_structure (caps, i);
+ if (i > 0)
+ g_string_append (s, "; ");
- g_string_append (s, "; ");
+ structure = gst_caps_get_structure (caps, i);
sstr = gst_structure_to_string (structure);
g_string_append (s, sstr);
g_free (sstr);
(xmlChar *) GST_PLUGIN_FEATURE (factory)->name);
}
-/* FIXME: what is this? */
-/* if (element->manager) */
-/* xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); */
-
/* params */
specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
gst_value_collect_int_range (GValue * value, guint n_collect_values,
GTypeCValue * collect_values, guint collect_flags)
{
- /* FIXME */
value->data[0].v_int = collect_values[0].v_int;
value->data[1].v_int = collect_values[1].v_int;
return d;
}
-/* FIXME: wouldn't it be nice if this function
- * were documented ? Alphabet spaghetti is easier to digest.
+/*
+ * This function takes a string delimited with double quotes (")
+ * and unescapes any \xxx octal numbers.
+ *
+ * If sequences of \y are found where y is not in the range of
+ * 0->3, y is copied unescaped.
+ *
+ * If \xyy is found where x is an octal number but y is not, an
+ * error is encountered and NULL is returned.
+ *
+ * the input string must be \0 terminated.
*/
static char *
gst_string_unwrap (const gchar * s)
gchar *ret;
gchar *read, *write;
+ /* NULL string returns NULL */
if (s == NULL)
return NULL;
+ /* strings not starting with " are invalid */
+ if (*s != '"')
+ return NULL;
+
+ /* make copy of original string to hold the result. This
+ * string will always be smaller than the original */
ret = g_strdup (s);
read = ret;
write = ret;
- if (*read++ != '"')
- goto beach;
+ /* need to move to the next position as we parsed the " */
+ read++;
while (*read) {
if (GST_ASCII_IS_STRING (*read)) {
+ /* normal chars are just copied */
*write++ = *read++;
} else if (*read == '"') {
+ /* quote marks end of string */
break;
} else if (*read == '\\') {
+ /* got an escape char, move to next position to read a tripplet
+ * of octal numbers */
read++;
- if (*read >= '0' && *read <= '7') {
+ /* is the next char a possible first octal number? */
+ if (*read >= '0' && *read <= '3') {
+ /* parse other 2 numbers, if one of them is not in the range of
+ * an octal number, we error. We also catch the case where a zero
+ * byte is found here. */
if (read[1] < '0' || read[1] > '7' || read[2] < '0' || read[2] > '7')
goto beach;
+ /* now convert the octal number to a byte again. */
*write++ = ((read[0] - '0') << 6) +
((read[1] - '0') << 3) + (read[2] - '0');
+
read += 3;
} else {
/* if we run into a \0 here, we definately won't get a quote later */
if (*read == 0)
goto beach;
+ /* else copy \X sequence */
*write++ = *read++;
}
} else {
+ /* weird character, error */
goto beach;
}
}
+ /* if the string is not ending in " and zero terminated, we error */
if (*read != '"' || read[1] != '\0')
goto beach;
+ /* null terminate result string and return */
*write++ = '\0';
return ret;
gst_value_union_int_int_range (GValue * dest, const GValue * src1,
const GValue * src2)
{
- g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_INT, FALSE);
- g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
-
if (src2->data[0].v_int <= src1->data[0].v_int &&
src2->data[1].v_int >= src1->data[0].v_int) {
gst_value_init_and_copy (dest, src2);
return TRUE;
}
-
return FALSE;
}
int min;
int max;
- g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_INT_RANGE, FALSE);
- g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
-
min = MAX (src1->data[0].v_int, src2->data[0].v_int);
max = MIN (src1->data[1].v_int, src2->data[1].v_int);
gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
const GValue * src2)
{
- g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_INT, FALSE);
- g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
-
if (src2->data[0].v_int <= src1->data[0].v_int &&
src2->data[1].v_int >= src1->data[0].v_int) {
gst_value_init_and_copy (dest, src1);
int min;
int max;
- g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_INT_RANGE, FALSE);
- g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
-
min = MAX (src1->data[0].v_int, src2->data[0].v_int);
max = MIN (src1->data[1].v_int, src2->data[1].v_int);
gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
const GValue * src2)
{
- g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_DOUBLE, FALSE);
- g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_DOUBLE_RANGE, FALSE);
-
if (src2->data[0].v_double <= src1->data[0].v_double &&
src2->data[1].v_double >= src1->data[0].v_double) {
gst_value_init_and_copy (dest, src1);
double min;
double max;
- g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_DOUBLE_RANGE, FALSE);
- g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_DOUBLE_RANGE, FALSE);
-
min = MAX (src1->data[0].v_double, src2->data[0].v_double);
max = MIN (src1->data[1].v_double, src2->data[1].v_double);
GValue intersection = { 0, };
gboolean ret = FALSE;
- g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value1), FALSE);
-
size = gst_value_list_get_size (value1);
for (i = 0; i < size; i++) {
const GValue *cur = gst_value_list_get_value (value1, i);
int max = gst_value_get_int_range_max (subtrahend);
int val = g_value_get_int (minuend);
+ /* subtracting a range from an int only works if the int is not in the
+ * range */
if (val < min || val > max) {
+ /* and the result is the int */
gst_value_init_and_copy (dest, minuend);
return TRUE;
}
return FALSE;
}
+/* creates a new int range based on input values.
+ */
static gboolean
gst_value_create_new_range (GValue * dest, int min1, int max1, int min2,
int max2)
g_return_val_if_fail (min < max, FALSE);
+ /* value is outside of the range, return range unchanged */
if (val < min || val > max) {
gst_value_init_and_copy (dest, minuend);
return TRUE;
} else {
+ /* max must be MAXINT too as val <= max */
if (val == G_MAXINT) {
max--;
val--;
}
+ /* min must be MININT too as val >= max */
if (val == G_MININT) {
min++;
val++;
gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend,
const GValue * subtrahend)
{
- /* FIXME! */
+ /* since we don't have open ranges, we cannot create a hole in
+ * a double range. We return the original range */
gst_value_init_and_copy (dest, minuend);
return TRUE;
}
gst_value_subtract_double_range_double_range (GValue * dest,
const GValue * minuend, const GValue * subtrahend)
{
- /* FIXME! */
+ /* since we don't have open ranges, we have to approximate */
/* done like with ints */
double min1 = gst_value_get_double_range_min (minuend);
double max2 = gst_value_get_double_range_max (minuend);
GValue subtraction = { 0, };
gboolean ret = FALSE;
- g_return_val_if_fail (GST_VALUE_HOLDS_LIST (minuend), FALSE);
-
size = gst_value_list_get_size (minuend);
for (i = 0; i < size; i++) {
const GValue *cur = gst_value_list_get_value (minuend, i);
GValue data[2] = { {0,}, {0,} };
GValue *subtraction = &data[0], *result = &data[1];
- g_return_val_if_fail (GST_VALUE_HOLDS_LIST (subtrahend), FALSE);
-
gst_value_init_and_copy (result, minuend);
size = gst_value_list_get_size (subtrahend);
for (i = 0; i < size; i++) {
if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
return FALSE;
+
for (i = 0; i < gst_value_table->len; i++) {
table = &g_array_index (gst_value_table, GstValueTable, i);
if (g_type_is_a (G_VALUE_TYPE (value1), table->type) && table->compare)
static int
gst_value_compare_fraction (const GValue * value1, const GValue * value2)
{
- /* FIXME: maybe we should make this more mathematically correct instead
- * of approximating with gdoubles */
-
gint n1, n2;
gint d1, d2;
- gdouble new_num_1;
- gdouble new_num_2;
+ gint64 new_num_1;
+ gint64 new_num_2;
n1 = value1->data[0].v_int;
n2 = value2->data[0].v_int;
if (n1 == n2 && d1 == d2)
return GST_VALUE_EQUAL;
- new_num_1 = n1 * d2;
- new_num_2 = n2 * d1;
+ /* extend to 64 bits */
+ new_num_1 = ((gint64) n1) * d2;
+ new_num_2 = ((gint64) n2) * d1;
if (new_num_1 < new_num_2)
return GST_VALUE_LESS_THAN;
if (new_num_1 > new_num_2)
return GST_VALUE_GREATER_THAN;
+
g_assert_not_reached ();
return GST_VALUE_UNORDERED;
}
g_value_init (&src1, G_TYPE_INT);
g_value_set_int (&src1, 10);
g_value_init (&src2, G_TYPE_INT);
- g_value_set_int (&src1, 20);
+ g_value_set_int (&src2, 20);
ret = gst_value_intersect (&dest, &src1, &src2);
- fail_unless (ret == 0);
+ fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
GST_END_TEST;
+
+GST_START_TEST (test_value_subtract_int)
+{
+ GValue dest = { 0 };
+ GValue src1 = { 0 };
+ GValue src2 = { 0 };
+ const GValue *tmp;
+ gboolean ret;
+
+ /* int <-> int
+ */
+ g_value_init (&src1, G_TYPE_INT);
+ g_value_set_int (&src1, 10);
+ g_value_init (&src2, G_TYPE_INT);
+ g_value_set_int (&src2, 20);
+ /* subtract as in sets, result is 10 */
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
+ g_value_unset (&dest);
+
+ /* same values, yields empty set */
+ ret = gst_value_subtract (&dest, &src1, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* int <-> int_range
+ */
+
+ /* would yield an empty set */
+ g_value_init (&src1, G_TYPE_INT);
+ g_value_set_int (&src1, 10);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 0, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, should create a list of two ranges. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 0);
+ fail_unless (gst_value_get_int_range_max (tmp) == 9);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 11);
+ fail_unless (gst_value_get_int_range_max (tmp) == 20);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* border case 1, empty set */
+ g_value_init (&src1, G_TYPE_INT);
+ g_value_set_int (&src1, 10);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 10, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, should create a new range. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 11);
+ fail_unless (gst_value_get_int_range_max (&dest) == 20);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* border case 2, empty set */
+ g_value_init (&src1, G_TYPE_INT);
+ g_value_set_int (&src1, 20);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 10, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, should create a new range. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 10);
+ fail_unless (gst_value_get_int_range_max (&dest) == 19);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* case 3, valid set */
+ g_value_init (&src1, G_TYPE_INT);
+ g_value_set_int (&src1, 0);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 10, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (G_VALUE_HOLDS_INT (&dest) == TRUE);
+ fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
+ g_value_unset (&dest);
+
+ /* and the other way around, should keep the range. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 10);
+ fail_unless (gst_value_get_int_range_max (&dest) == 20);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* int_range <-> int_range
+ */
+
+ /* same range, empty set */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 20);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 10, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* non overlapping ranges */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 20);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 30, 40);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 10);
+ fail_unless (gst_value_get_int_range_max (&dest) == 20);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 30);
+ fail_unless (gst_value_get_int_range_max (&dest) == 40);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* completely overlapping ranges */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 20);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 10, 30);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 21);
+ fail_unless (gst_value_get_int_range_max (&dest) == 30);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* partially overlapping ranges */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 20);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 15, 30);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 10);
+ fail_unless (gst_value_get_int_range_max (&dest) == 14);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_int_range_min (&dest) == 21);
+ fail_unless (gst_value_get_int_range_max (&dest) == 30);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* create a hole { int_range, int_range } */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 30);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 15, 20);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 10);
+ fail_unless (gst_value_get_int_range_max (tmp) == 14);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 21);
+ fail_unless (gst_value_get_int_range_max (tmp) == 30);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* create a hole, { int, int } */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 30);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 11, 29);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
+ fail_unless (g_value_get_int (tmp) == 10);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
+ fail_unless (g_value_get_int (tmp) == 30);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* create a hole, { int, int_range } */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 30);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 11, 28);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
+ fail_unless (g_value_get_int (tmp) == 10);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 29);
+ fail_unless (gst_value_get_int_range_max (tmp) == 30);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* create a hole, { int_range, int } */
+ g_value_init (&src1, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src1, 10, 30);
+ g_value_init (&src2, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&src2, 12, 29);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_int_range_min (tmp) == 10);
+ fail_unless (gst_value_get_int_range_max (tmp) == 11);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
+ fail_unless (g_value_get_int (tmp) == 30);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_value_subtract_double)
+{
+ GValue dest = { 0 };
+ GValue src1 = { 0 };
+ GValue src2 = { 0 };
+ const GValue *tmp;
+ gboolean ret;
+
+ /* double <-> double
+ */
+ g_value_init (&src1, G_TYPE_DOUBLE);
+ g_value_set_double (&src1, 10.0);
+ g_value_init (&src2, G_TYPE_DOUBLE);
+ g_value_set_double (&src2, 20.0);
+ /* subtract as in sets, result is 10 */
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
+ g_value_unset (&dest);
+
+ /* same values, yields empty set */
+ ret = gst_value_subtract (&dest, &src1, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* double <-> double_range
+ */
+
+ /* would yield an empty set */
+ g_value_init (&src1, G_TYPE_DOUBLE);
+ g_value_set_double (&src1, 10.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 0.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, we cannot create open ranges
+ * so the result is the range again */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 0.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* border case 1, empty set */
+ g_value_init (&src1, G_TYPE_DOUBLE);
+ g_value_set_double (&src1, 10.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 10.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, should keep same range as
+ * we don't have open ranges. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* border case 2, empty set */
+ g_value_init (&src1, G_TYPE_DOUBLE);
+ g_value_set_double (&src1, 20.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 10.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+
+ /* and the other way around, should keep same range as
+ * we don't have open ranges. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* case 3, valid set */
+ g_value_init (&src1, G_TYPE_DOUBLE);
+ g_value_set_double (&src1, 0.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 10.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (G_VALUE_HOLDS_DOUBLE (&dest) == TRUE);
+ fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
+ g_value_unset (&dest);
+
+ /* and the other way around, should keep the range. */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* double_range <-> double_range
+ */
+
+ /* same range, empty set */
+ g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src1, 10.0, 20.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 10.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* non overlapping ranges */
+ g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src1, 10.0, 20.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 30.0, 40.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 30.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 40.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* completely overlapping ranges */
+ g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src1, 10.0, 20.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 10.0, 30.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == FALSE);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 20.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 30.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* partially overlapping ranges */
+ g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src1, 10.0, 20.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 15.0, 30.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 15.0);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (&dest) == TRUE);
+ fail_unless (gst_value_get_double_range_min (&dest) == 20.0);
+ fail_unless (gst_value_get_double_range_max (&dest) == 30.0);
+ g_value_unset (&dest);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+
+ /* create a hole { double_range, double_range } */
+ g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src1, 10.0, 30.0);
+ g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
+ gst_value_set_double_range (&src2, 15.0, 20.0);
+ ret = gst_value_subtract (&dest, &src1, &src2);
+ fail_unless (ret == TRUE);
+ fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ tmp = gst_value_list_get_value (&dest, 0);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_double_range_min (tmp) == 10.0);
+ fail_unless (gst_value_get_double_range_max (tmp) == 15.0);
+ tmp = gst_value_list_get_value (&dest, 1);
+ fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (tmp) == TRUE);
+ fail_unless (gst_value_get_double_range_min (tmp) == 20.0);
+ fail_unless (gst_value_get_double_range_max (tmp) == 30.0);
+ g_value_unset (&dest);
+ /* the other way */
+ ret = gst_value_subtract (&dest, &src2, &src1);
+ fail_unless (ret == FALSE);
+ g_value_unset (&src1);
+ g_value_unset (&src2);
+}
+
+GST_END_TEST;
+
Suite *
gst_value_suite (void)
{
tcase_add_test (tc_chain, test_deserialize_string);
tcase_add_test (tc_chain, test_value_compare);
tcase_add_test (tc_chain, test_value_intersect);
+ tcase_add_test (tc_chain, test_value_subtract_int);
+ tcase_add_test (tc_chain, test_value_subtract_double);
+
return s;
}