diff --git a/ChangeLog b/ChangeLog index 6f86ff6192..7516eb8a0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2005-08-16 Wim Taymans + + * 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 * tools/gst-launch.c: (event_loop): diff --git a/check/gst/gstvalue.c b/check/gst/gstvalue.c index 7a6fcdba0d..4dc3dae289 100644 --- a/check/gst/gstvalue.c +++ b/check/gst/gstvalue.c @@ -411,9 +411,9 @@ GST_START_TEST (test_value_intersect) 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); @@ -436,6 +436,489 @@ GST_START_TEST (test_value_intersect) 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) { @@ -453,6 +936,9 @@ 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; } diff --git a/docs/design/part-events.txt b/docs/design/part-events.txt index ed671f4a1f..bc7eef56df 100644 --- a/docs/design/part-events.txt +++ b/docs/design/part-events.txt @@ -122,6 +122,11 @@ Buffers should be clipped within the range indicated by the newsegment event 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 ---- diff --git a/gst/gstbin.c b/gst/gstbin.c index 5ffd72c3c9..bbb9c8ea85 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -1175,9 +1175,9 @@ restart: 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); @@ -1439,14 +1439,12 @@ gst_bin_send_event (GstElement * element, GstEvent * event) 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)); @@ -1454,10 +1452,12 @@ bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin) 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), diff --git a/gst/gstcaps.c b/gst/gstcaps.c index e77442d302..6a78b2a4e0 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -1525,9 +1525,7 @@ gchar * 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.) @@ -1535,8 +1533,6 @@ gst_caps_to_string (const GstCaps * caps) * 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"); } @@ -1546,16 +1542,16 @@ gst_caps_to_string (const GstCaps * caps) 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; + + if (i > 0) + g_string_append (s, "; "); - for (i = 1; i < caps->structs->len; i++) { structure = gst_caps_get_structure (caps, i); - - g_string_append (s, "; "); sstr = gst_structure_to_string (structure); g_string_append (s, sstr); g_free (sstr); diff --git a/gst/gstelement.c b/gst/gstelement.c index a37e841a19..6d1ccc1142 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -2122,10 +2122,6 @@ gst_element_save_thyself (GstObject * object, xmlNodePtr parent) (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); diff --git a/gst/gstvalue.c b/gst/gstvalue.c index aa3ad0126d..3c01829e65 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -578,7 +578,6 @@ static gchar * 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; @@ -1347,8 +1346,17 @@ gst_string_wrap (const char *s) 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) @@ -1356,44 +1364,65 @@ 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; @@ -1597,15 +1626,11 @@ static gboolean 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; } @@ -1616,9 +1641,6 @@ gst_value_union_int_range_int_range (GValue * dest, const GValue * 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); @@ -1641,9 +1663,6 @@ static gboolean 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); @@ -1660,9 +1679,6 @@ gst_value_intersect_int_range_int_range (GValue * dest, const GValue * 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); @@ -1684,9 +1700,6 @@ static gboolean 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); @@ -1703,9 +1716,6 @@ gst_value_intersect_double_range_double_range (GValue * dest, 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); @@ -1731,8 +1741,6 @@ gst_value_intersect_list (GValue * dest, const GValue * value1, 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); @@ -1797,13 +1805,18 @@ gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend, 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) @@ -1858,14 +1871,17 @@ gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend, 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++; @@ -1915,7 +1931,8 @@ static gboolean 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; } @@ -1924,7 +1941,7 @@ static gboolean 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); @@ -1972,8 +1989,6 @@ gst_value_subtract_from_list (GValue * dest, const GValue * 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); @@ -2014,8 +2029,6 @@ gst_value_subtract_list (GValue * dest, const GValue * minuend, 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++) { @@ -2059,6 +2072,7 @@ gst_value_can_compare (const GValue * value1, const GValue * value2) 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) @@ -2924,14 +2938,11 @@ gst_value_transform_fraction_double (const GValue * src_value, 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; @@ -2942,12 +2953,14 @@ gst_value_compare_fraction (const GValue * value1, const GValue * value2) 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; } diff --git a/tests/check/gst/gstvalue.c b/tests/check/gst/gstvalue.c index 7a6fcdba0d..4dc3dae289 100644 --- a/tests/check/gst/gstvalue.c +++ b/tests/check/gst/gstvalue.c @@ -411,9 +411,9 @@ GST_START_TEST (test_value_intersect) 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); @@ -436,6 +436,489 @@ GST_START_TEST (test_value_intersect) 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) { @@ -453,6 +936,9 @@ 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; }