diff --git a/ChangeLog b/ChangeLog index 0eb01f95c7..6e9fe4d2b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2005-11-22 Jan Schmidt + + * check/gst/capslist.h: + * check/gst/gstcaps.c: (GST_START_TEST): + * check/gst/gstvalue.c: (GST_START_TEST), (gst_value_suite): + * gst/gststructure.c: (gst_structure_parse_range), + (gst_structure_fixate_field_nearest_fraction): + * gst/gststructure.h: + * gst/gstvalue.c: (gst_value_init_fraction_range), + (gst_value_free_fraction_range), (gst_value_copy_fraction_range), + (gst_value_collect_fraction_range), + (gst_value_lcopy_fraction_range), (gst_value_set_fraction_range), + (gst_value_set_fraction_range_full), + (gst_value_get_fraction_range_min), + (gst_value_get_fraction_range_max), + (gst_value_serialize_fraction_range), + (gst_value_transform_fraction_range_string), + (gst_value_compare_fraction_range), + (gst_value_deserialize_fraction_range), + (gst_value_intersect_fraction_fraction_range), + (gst_value_intersect_fraction_range_fraction_range), + (gst_value_subtract_fraction_fraction_range), + (gst_value_subtract_fraction_range_fraction), + (gst_value_subtract_fraction_range_fraction_range), + (gst_value_collect_fraction), (gst_value_fraction_multiply), + (gst_value_fraction_subtract), (gst_value_deserialize_fraction), + (gst_value_transform_string_fraction), (_gst_value_initialize): + * gst/gstvalue.h: + Implement fraction ranges and extend GstFraction to support + arithmetic subtraction, as well as deserialization from integer + strings such as "100" + Add a testsuite as for int and double range set operations + 2005-11-21 Andy Wingo * gst/gsttaglist.h: diff --git a/check/gst/capslist.h b/check/gst/capslist.h index 8b84acafc9..894a905b39 100644 --- a/check/gst/capslist.h +++ b/check/gst/capslist.h @@ -15,6 +15,10 @@ static const gchar *caps_list[] = { "video/x-raw-rgb, bpp = (int) 32, depth = (int) 24, endianness = (int) BIG_ENDIAN, red_mask = (int) 0x000000FF, framerate = (double) [ 0, max ]", "video/x-raw-rgb, bpp = (int) 32, depth = (int) 24, endianness = (int) BIG_ENDIAN, red_mask = (int) 0xFF000000, framerate = (double) [ 0, max ]", "video/x-raw-rgb,\\ bpp=(int)32", + "test/gst-fraction, fraction = (fraction) 1/8", + "test/gst-fraction-range, fraction = (fraction) [ 1/3, 1/4 ]", + "test/gst-fraction-range, fraction = (fraction) { [ 1/3, 1/4 ], 1/8 }", + "test/gst-fraction-range, fraction = (fraction) { [ 1/3, 1/4 ], [ 1/8, 2/8 ] }", "ANY", "EMPTY" }; diff --git a/check/gst/gstcaps.c b/check/gst/gstcaps.c index 1df100b6d0..75e81de95f 100644 --- a/check/gst/gstcaps.c +++ b/check/gst/gstcaps.c @@ -128,14 +128,14 @@ GST_START_TEST (test_static_caps) GST_END_TEST; static const gchar non_simple_caps_string[] = - "video/x-raw-yuv, format=(fourcc)I420, framerate=(double)[ 1, 100 ], " + "video/x-raw-yuv, format=(fourcc)I420, framerate=(fraction)[ 1/100, 100 ], " "width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-yuv, " - "format=(fourcc)YUY2, framerate=(double)[ 1, 100 ], width=(int)[ 16, 4096 ], " + "format=(fourcc)YUY2, framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], " "height=(int)[ 16, 4096 ]; video/x-raw-rgb, bpp=(int)8, depth=(int)8, " - "endianness=(int)1234, framerate=(double)[ 1, 100 ], width=(int)[ 16, 4096 ], " + "endianness=(int)1234, framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], " "height=(int)[ 16, 4096 ]; video/x-raw-yuv, " "format=(fourcc){ I420, YUY2, YV12 }, width=(int)[ 16, 4096 ], " - "height=(int)[ 16, 4096 ], framerate=(double)[ 1, 100 ]"; + "height=(int)[ 16, 4096 ], framerate=(fraction)[ 1/100, 100 ]"; static gboolean check_fourcc_list (const GValue * format_value) @@ -193,11 +193,11 @@ GST_START_TEST (test_simplify) /* check simplified caps, should be: * * video/x-raw-rgb, bpp=(int)8, depth=(int)8, endianness=(int)1234, - * framerate=(double)[ 1, 100 ], width=(int)[ 16, 4096 ], + * framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], * height=(int)[ 16, 4096 ]; * video/x-raw-yuv, format=(fourcc){ YV12, YUY2, I420 }, * width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], - * framerate=(double)[ 1, 100 ] + * framerate=(fraction)[ 1/100, 100 ] */ fail_unless (gst_caps_get_size (caps) == 2); s1 = gst_caps_get_structure (caps, 0); @@ -218,7 +218,8 @@ GST_START_TEST (test_simplify) const GValue *framerate_value; const GValue *width_value; const GValue *height_value; - gdouble min_fps, max_fps; + const GValue *val_fps; + GValue test_fps = { 0, }; gint bpp, depth, endianness; gint min_width, max_width; gint min_height, max_height; @@ -232,12 +233,20 @@ GST_START_TEST (test_simplify) fail_unless (gst_structure_get_int (s1, "endianness", &endianness)); fail_unless (endianness == G_LITTLE_ENDIAN); + g_value_init (&test_fps, GST_TYPE_FRACTION); framerate_value = gst_structure_get_value (s1, "framerate"); fail_unless (framerate_value != NULL); - fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (framerate_value)); - min_fps = gst_value_get_double_range_min (framerate_value); - max_fps = gst_value_get_double_range_max (framerate_value); - fail_unless (min_fps == 1.0 && max_fps == 100.0); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (framerate_value)); + + val_fps = gst_value_get_fraction_range_min (framerate_value); + gst_value_set_fraction (&test_fps, 1, 100); + fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL); + + val_fps = gst_value_get_fraction_range_max (framerate_value); + gst_value_set_fraction (&test_fps, 100, 1); + fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL); + + g_value_unset (&test_fps); width_value = gst_structure_get_value (s1, "width"); fail_unless (width_value != NULL); @@ -260,7 +269,8 @@ GST_START_TEST (test_simplify) const GValue *format_value; const GValue *width_value; const GValue *height_value; - gdouble min_fps, max_fps; + const GValue *val_fps; + GValue test_fps = { 0, }; gint min_width, max_width; gint min_height, max_height; @@ -270,12 +280,20 @@ GST_START_TEST (test_simplify) fail_unless (gst_value_list_get_size (format_value) == 3); fail_unless (check_fourcc_list (format_value) == TRUE); + g_value_init (&test_fps, GST_TYPE_FRACTION); framerate_value = gst_structure_get_value (s2, "framerate"); fail_unless (framerate_value != NULL); - fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (framerate_value)); - min_fps = gst_value_get_double_range_min (framerate_value); - max_fps = gst_value_get_double_range_max (framerate_value); - fail_unless (min_fps == 1.0 && max_fps == 100.0); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (framerate_value)); + + val_fps = gst_value_get_fraction_range_min (framerate_value); + gst_value_set_fraction (&test_fps, 1, 100); + fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL); + + val_fps = gst_value_get_fraction_range_max (framerate_value); + gst_value_set_fraction (&test_fps, 100, 1); + fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL); + + g_value_unset (&test_fps); width_value = gst_structure_get_value (s2, "width"); fail_unless (width_value != NULL); diff --git a/check/gst/gstvalue.c b/check/gst/gstvalue.c index 61774d32ba..1da8e06295 100644 --- a/check/gst/gstvalue.c +++ b/check/gst/gstvalue.c @@ -435,6 +435,7 @@ GST_START_TEST (test_value_compare) fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); g_value_unset (&value1); g_value_unset (&value2); + } GST_END_TEST; @@ -958,6 +959,280 @@ GST_START_TEST (test_value_subtract_double) GST_END_TEST; +/* Test arithmetic subtraction of fractions */ +GST_START_TEST (test_value_subtract_fraction) +{ + GValue result = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + + /* Subtract 1/4 from 1/2 */ + g_value_init (&src1, GST_TYPE_FRACTION); + g_value_init (&src2, GST_TYPE_FRACTION); + g_value_init (&result, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 1, 2); + gst_value_set_fraction (&src2, 1, 4); + fail_unless (gst_value_fraction_subtract (&result, &src1, &src2) == TRUE); + fail_unless (gst_value_get_fraction_numerator (&result) == 1); + fail_unless (gst_value_get_fraction_denominator (&result) == 4); + + g_value_unset (&src1); + g_value_unset (&src2); + g_value_unset (&result); + + /* Subtract 1/12 from 7/8 */ + g_value_init (&src1, GST_TYPE_FRACTION); + g_value_init (&src2, GST_TYPE_FRACTION); + g_value_init (&result, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 7, 8); + gst_value_set_fraction (&src2, 1, 12); + fail_unless (gst_value_fraction_subtract (&result, &src1, &src2) == TRUE); + fail_unless (gst_value_get_fraction_numerator (&result) == 19); + fail_unless (gst_value_get_fraction_denominator (&result) == 24); + + g_value_unset (&src1); + g_value_unset (&src2); + g_value_unset (&result); +} + +GST_END_TEST; + +/* Test set subtraction operations on fraction ranges */ +GST_START_TEST (test_value_subtract_fraction_range) +{ + GValue dest = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + GValue cmp = { 0 }; + const GValue *tmp; + gboolean ret; + + /* Value for tests */ + g_value_init (&cmp, GST_TYPE_FRACTION); + + /* fraction <-> fraction + */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION); + gst_value_set_fraction (&src2, 20, 1); + gst_value_set_fraction (&src1, 10, 1); + + /* 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); + + /* fraction <-> fraction_range + */ + + /* would yield an empty set */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 0, 1, 20, 1); + 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_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 0, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 1, empty set */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 1, 20, 1); + 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_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* case 2, valid set */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 0, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 1, 20, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_FRACTION (&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_FRACTION_RANGE (&dest) == TRUE); + fail_unless (gst_value_compare (&dest, &src2) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* fraction_range <-> fraction_range + */ + + /* same range, empty set */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 2, 20, 2); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 2, 20, 2); + 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_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 2, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 30, 2, 40, 2); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 5, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 15, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* completely overlapping ranges */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 1, 20, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 1, 30, 1); + 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_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 30, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* partially overlapping ranges */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 1, 20, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 15, 1, 30, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 15, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 30, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + 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_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 1, 30, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 15, 1, 20, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE); + /* 1st list entry */ + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (tmp) == TRUE); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (tmp), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 15, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (tmp), + &cmp) == GST_VALUE_EQUAL); + /* 2nd list entry */ + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (tmp) == TRUE); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (tmp), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 30, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (tmp), + &cmp) == GST_VALUE_EQUAL); + 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); + + g_value_unset (&cmp); +} + +GST_END_TEST; + GST_START_TEST (test_date) { GstStructure *s; @@ -1017,6 +1292,59 @@ GST_START_TEST (test_date) GST_END_TEST; +GST_START_TEST (test_fraction_range) +{ + GValue range = { 0, }; + GValue start = { 0, }, end = { + 0,}; + GValue src = { 0, }, dest = { + 0,}; + GValue range2 = { 0, }; + + g_value_init (&range, GST_TYPE_FRACTION_RANGE); + g_value_init (&range2, GST_TYPE_FRACTION_RANGE); + g_value_init (&start, GST_TYPE_FRACTION); + g_value_init (&end, GST_TYPE_FRACTION); + g_value_init (&src, GST_TYPE_FRACTION); + + gst_value_set_fraction (&src, 1, 2); + + /* Check that a intersection of fraction & range = fraction */ + gst_value_set_fraction (&start, 1, 4); + gst_value_set_fraction (&end, 2, 3); + gst_value_set_fraction_range (&range, &start, &end); + + fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION); + fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL); + + /* Check that a intersection selects the overlapping range */ + gst_value_set_fraction (&start, 1, 3); + gst_value_set_fraction (&end, 2, 3); + gst_value_set_fraction_range (&range2, &start, &end); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + + gst_value_set_fraction_range (&range2, &start, &end); + fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL); + + /* Check that non intersection ranges don't intersect */ + gst_value_set_fraction (&start, 4, 2); + gst_value_set_fraction (&end, 5, 2); + gst_value_set_fraction_range (&range2, &start, &end); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE); + + g_value_unset (&start); + g_value_unset (&end); + g_value_unset (&range); + g_value_unset (&range2); + g_value_unset (&src); +} + +GST_END_TEST; + Suite * gst_value_suite (void) { @@ -1037,7 +1365,10 @@ gst_value_suite (void) 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); + tcase_add_test (tc_chain, test_value_subtract_fraction); + tcase_add_test (tc_chain, test_value_subtract_fraction_range); tcase_add_test (tc_chain, test_date); + tcase_add_test (tc_chain, test_fraction_range); return s; } diff --git a/gst/gststructure.c b/gst/gststructure.c index ad8319722f..7d62243acc 100644 --- a/gst/gststructure.c +++ b/gst/gststructure.c @@ -1427,19 +1427,20 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value, if (G_VALUE_TYPE (&value1) == G_TYPE_DOUBLE) { range_type = GST_TYPE_DOUBLE_RANGE; - } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) { - range_type = GST_TYPE_INT_RANGE; - } else { - return FALSE; - } - - g_value_init (value, range_type); - if (range_type == GST_TYPE_DOUBLE_RANGE) { + g_value_init (value, range_type); gst_value_set_double_range (value, g_value_get_double (&value1), g_value_get_double (&value2)); - } else { + } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) { + range_type = GST_TYPE_INT_RANGE; + g_value_init (value, range_type); gst_value_set_int_range (value, g_value_get_int (&value1), g_value_get_int (&value2)); + } else if (G_VALUE_TYPE (&value1) == GST_TYPE_FRACTION) { + range_type = GST_TYPE_FRACTION_RANGE; + g_value_init (value, range_type); + gst_value_set_fraction_range (value, &value1, &value2); + } else { + return FALSE; } *after = s; @@ -1927,3 +1928,80 @@ gst_structure_fixate_field_boolean (GstStructure * structure, return FALSE; } + +/** + * gst_structure_fixate_field_nearest_fraction: + * @structure: a #GstStructure + * @field_name: a field in @structure + * @target: A GValue of GST_TYPE_FRACTION with the target value of the fixation + * + * Fixates a #GstStructure by changing the given field to the nearest + * integer to @target that is a subset of the existing field. + * + * Returns: TRUE if the structure could be fixated + */ +gboolean +gst_structure_fixate_field_nearest_fraction (GstStructure * structure, + const char *field_name, const GValue * target) +{ + const GValue *value; + + g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE); + g_return_val_if_fail (IS_MUTABLE (structure), FALSE); + g_return_val_if_fail (G_VALUE_TYPE (target) == GST_TYPE_FRACTION, FALSE); + + value = gst_structure_get_value (structure, field_name); + + if (G_VALUE_TYPE (value) == GST_TYPE_FRACTION) { + /* already fixed */ + return FALSE; + } else if (G_VALUE_TYPE (value) == GST_TYPE_FRACTION_RANGE) { + const GValue *x; + + x = gst_value_get_fraction_range_min (value); + if (gst_value_compare (target, x) == GST_VALUE_LESS_THAN) + target = x; + x = gst_value_get_fraction_range_max (value); + if (gst_value_compare (target, x) == GST_VALUE_GREATER_THAN) + target = x; + gst_structure_set_value (structure, field_name, target); + return TRUE; + } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) { + const GValue *list_value; + int i, n; + const GValue *best = NULL; + GValue best_diff; + GValue cur_diff; + + g_value_init (&best_diff, GST_TYPE_FRACTION); + g_value_init (&cur_diff, GST_TYPE_FRACTION); + + n = gst_value_list_get_size (value); + for (i = 0; i < n; i++) { + list_value = gst_value_list_get_value (value, i); + if (G_VALUE_TYPE (list_value) == GST_TYPE_FRACTION) { + if (best == NULL) { + best = list_value; + gst_value_set_fraction (&best_diff, 0, 1); + } else { + if (gst_value_compare (list_value, target) == GST_VALUE_LESS_THAN) + gst_value_fraction_subtract (&cur_diff, target, list_value); + else + gst_value_fraction_subtract (&cur_diff, list_value, target); + + if (gst_value_compare (&cur_diff, &best_diff) == GST_VALUE_LESS_THAN) { + best = list_value; + g_value_copy (&cur_diff, &best_diff); + } + } + } + } + if (best != NULL) { + gst_structure_set_value (structure, field_name, best); + return TRUE; + } + return FALSE; + } + + return FALSE; +} diff --git a/gst/gststructure.h b/gst/gststructure.h index 635ddaf4b2..57d8befa44 100644 --- a/gst/gststructure.h +++ b/gst/gststructure.h @@ -189,7 +189,9 @@ gboolean gst_structure_fixate_field_nearest_double (GstStructure gboolean gst_structure_fixate_field_boolean (GstStructure *structure, const char *field_name, gboolean target); - +gboolean gst_structure_fixate_field_nearest_fraction (GstStructure *structure, + const char *field_name, + const GValue *target); G_END_DECLS diff --git a/gst/gstvalue.c b/gst/gstvalue.c index b194ede068..d6e567bfe5 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -61,6 +61,7 @@ struct _GstValueSubtractInfo }; GType gst_type_double_range; +GType gst_type_fraction_range; GType gst_type_list; GType gst_type_array; GType gst_type_fraction; @@ -71,6 +72,10 @@ static GArray *gst_value_union_funcs; static GArray *gst_value_intersect_funcs; static GArray *gst_value_subtract_funcs; +/* Forward declarations */ +static gint gst_greatest_common_divisor (gint a, gint b); +static char *gst_value_serialize_fraction (const GValue * value); + /******** * list * ********/ @@ -896,6 +901,254 @@ gst_value_deserialize_double_range (GValue * dest, const char *s) return FALSE; } +/**************** + * fraction range * + ****************/ + +static void +gst_value_init_fraction_range (GValue * value) +{ + GValue *vals; + + value->data[0].v_pointer = vals = g_new0 (GValue, 2); + g_value_init (&vals[0], GST_TYPE_FRACTION); + g_value_init (&vals[1], GST_TYPE_FRACTION); +} + +static void +gst_value_free_fraction_range (GValue * value) +{ + GValue *vals = (GValue *) value->data[0].v_pointer; + + if (vals != NULL) { + g_value_unset (&vals[0]); + g_value_unset (&vals[1]); + g_free (vals); + value->data[0].v_pointer = NULL; + } +} + +static void +gst_value_copy_fraction_range (const GValue * src_value, GValue * dest_value) +{ + GValue *vals = (GValue *) dest_value->data[0].v_pointer; + GValue *src_vals = (GValue *) src_value->data[0].v_pointer; + + if (vals == NULL) { + dest_value->data[0].v_pointer = vals = g_new0 (GValue, 2); + g_return_if_fail (vals != NULL); + g_value_init (&vals[0], GST_TYPE_FRACTION); + g_value_init (&vals[1], GST_TYPE_FRACTION); + } + + if (src_vals != NULL) { + g_value_copy (&src_vals[0], &vals[0]); + g_value_copy (&src_vals[1], &vals[1]); + } +} + +static gchar * +gst_value_collect_fraction_range (GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + GValue *vals = (GValue *) value->data[0].v_pointer; + + if (n_collect_values != 4) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + if (vals == NULL) + return g_strdup_printf ("Uninitialised `%s' passed", + G_VALUE_TYPE_NAME (value)); + + gst_value_set_fraction (&vals[0], collect_values[0].v_int, + collect_values[1].v_int); + gst_value_set_fraction (&vals[1], collect_values[2].v_int, + collect_values[3].v_int); + + return NULL; +} + +static gchar * +gst_value_lcopy_fraction_range (const GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + int i; + int *dest_values[4]; + GValue *vals = (GValue *) value->data[0].v_pointer; + + if (n_collect_values != 4) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + + for (i = 0; i < 4; i++) { + if (collect_values[i].v_pointer == NULL) { + return g_strdup_printf ("value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + } + dest_values[i] = collect_values[i].v_pointer; + } + + if (vals == NULL) { + return g_strdup_printf ("Uninitialised `%s' passed", + G_VALUE_TYPE_NAME (value)); + } + + dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]); + dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]); + dest_values[2][0] = gst_value_get_fraction_denominator (&vals[1]); + dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]); + return NULL; +} + +/** + * gst_value_set_fraction_range: + * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE + * @start: the start of the range (a GST_TYPE_FRACTION GValue) + * @end: the end of the range (a GST_TYPE_FRACTION GValue) + * + * Sets @value to the range specified by @start and @end. + */ +void +gst_value_set_fraction_range (GValue * value, const GValue * start, + const GValue * end) +{ + GValue *vals; + + g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value)); + + vals = (GValue *) value->data[0].v_pointer; + if (vals == NULL) { + value->data[0].v_pointer = vals = g_new0 (GValue, 2); + g_value_init (&vals[0], GST_TYPE_FRACTION); + g_value_init (&vals[1], GST_TYPE_FRACTION); + } + + g_value_copy (start, &vals[0]); + g_value_copy (end, &vals[1]); +} + +void +gst_value_set_fraction_range_full (GValue * value, + int numerator_start, int denominator_start, + int numerator_end, int denominator_end) +{ + GValue start = { 0 }; + GValue end = { 0 }; + + g_value_init (&start, GST_TYPE_FRACTION); + g_value_init (&end, GST_TYPE_FRACTION); + + gst_value_set_fraction (&start, numerator_start, denominator_start); + gst_value_set_fraction (&end, numerator_end, denominator_end); + gst_value_set_fraction_range (value, &start, &end); + + g_value_unset (&start); + g_value_unset (&end); +} + +/** + * gst_value_get_fraction_range_min: + * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE + * + * Gets the minimum of the range specified by @value. + * + * Returns: the minumum of the range + */ +const GValue * +gst_value_get_fraction_range_min (const GValue * value) +{ + GValue *vals; + + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), FALSE); + + vals = (GValue *) value->data[0].v_pointer; + if (vals != NULL) { + return &vals[0]; + } + + return NULL; +} + +/** + * gst_value_get_fraction_range_max: + * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE + * + * Gets the maximum of the range specified by @value. + * + * Returns: the maximum of the range + */ +const GValue * +gst_value_get_fraction_range_max (const GValue * value) +{ + GValue *vals; + + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), FALSE); + + vals = (GValue *) value->data[0].v_pointer; + if (vals != NULL) { + return &vals[1]; + } + + return NULL; +} + +static char * +gst_value_serialize_fraction_range (const GValue * value) +{ + GValue *vals = (GValue *) value->data[0].v_pointer; + gchar *retval; + + if (vals == NULL) { + retval = g_strdup ("[ 0/1, 0/1 ]"); + } else { + gchar *start, *end; + + start = gst_value_serialize_fraction (&vals[0]); + end = gst_value_serialize_fraction (&vals[1]); + + retval = g_strdup_printf ("[ %s, %s ]", start, end); + g_free (start); + g_free (end); + } + + return retval; +} + +static void +gst_value_transform_fraction_range_string (const GValue * src_value, + GValue * dest_value) +{ + dest_value->data[0].v_pointer = + gst_value_serialize_fraction_range (src_value); +} + +static int +gst_value_compare_fraction_range (const GValue * value1, const GValue * value2) +{ + GValue *vals1, *vals2; + + if (value2->data[0].v_pointer == value1->data[0].v_pointer) + return GST_VALUE_EQUAL; /* Only possible if both are NULL */ + + if (value2->data[0].v_pointer == NULL || value1->data[0].v_pointer == NULL) + return GST_VALUE_UNORDERED; + + vals1 = (GValue *) value1->data[0].v_pointer; + vals2 = (GValue *) value2->data[0].v_pointer; + if (gst_value_compare (&vals1[0], &vals2[0]) == GST_VALUE_EQUAL && + gst_value_compare (&vals1[1], &vals2[1]) == GST_VALUE_EQUAL) + return GST_VALUE_EQUAL; + + return GST_VALUE_UNORDERED; +} + +static gboolean +gst_value_deserialize_fraction_range (GValue * dest, const char *s) +{ + g_warning ("unimplemented"); + return FALSE; +} + /*********** * GstCaps * ***********/ @@ -1869,6 +2122,76 @@ gst_value_intersect_array (GValue * dest, const GValue * src1, return TRUE; } +static gboolean +gst_value_intersect_fraction_fraction_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + int res1, res2; + GValue *vals; + + vals = src2->data[0].v_pointer; + + if (vals == NULL) + return FALSE; + + res1 = gst_value_compare (&vals[0], src1); + res2 = gst_value_compare (&vals[1], src1); + + if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) && + (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) { + gst_value_init_and_copy (dest, src1); + return TRUE; + } + + return FALSE; +} + +static gboolean + gst_value_intersect_fraction_range_fraction_range + (GValue * dest, const GValue * src1, const GValue * src2) +{ + GValue *min; + GValue *max; + int res; + GValue *vals1, *vals2; + + vals1 = src1->data[0].v_pointer; + vals2 = src2->data[0].v_pointer; + g_return_val_if_fail (vals1 != NULL && vals2 != NULL, FALSE); + + /* min = MAX (src1.start, src2.start) */ + res = gst_value_compare (&vals1[0], &vals2[0]); + g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE); + if (res == GST_VALUE_LESS_THAN) + min = &vals2[0]; /* Take the max of the 2 */ + else + min = &vals1[0]; + + /* max = MIN (src1.end, src2.end) */ + res = gst_value_compare (&vals1[1], &vals2[1]); + g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE); + if (res == GST_VALUE_GREATER_THAN) + max = &vals2[1]; /* Take the min of the 2 */ + else + max = &vals1[1]; + + res = gst_value_compare (min, max); + g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE); + if (res == GST_VALUE_LESS_THAN) { + g_value_init (dest, GST_TYPE_FRACTION_RANGE); + vals1 = dest->data[0].v_pointer; + g_value_copy (min, &vals1[0]); + g_value_copy (max, &vals1[1]); + return TRUE; + } + if (res == GST_VALUE_EQUAL) { + gst_value_init_and_copy (dest, min); + return TRUE; + } + + return FALSE; +} + /*************** * subtraction * ***************/ @@ -2126,6 +2449,94 @@ gst_value_subtract_list (GValue * dest, const GValue * minuend, return TRUE; } +static gboolean +gst_value_subtract_fraction_fraction_range (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + const GValue *min = gst_value_get_fraction_range_min (subtrahend); + const GValue *max = gst_value_get_fraction_range_max (subtrahend); + + /* subtracting a range from an fraction only works if the fraction + * is not in the range */ + if (gst_value_compare (minuend, min) == GST_VALUE_LESS_THAN || + gst_value_compare (minuend, max) == GST_VALUE_GREATER_THAN) { + /* and the result is the value */ + gst_value_init_and_copy (dest, minuend); + return TRUE; + } + return FALSE; +} + +static gboolean +gst_value_subtract_fraction_range_fraction (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + /* since we don't have open ranges, we cannot create a hole in + * a range. We return the original range */ + gst_value_init_and_copy (dest, minuend); + return TRUE; +} + +static gboolean +gst_value_subtract_fraction_range_fraction_range (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + /* since we don't have open ranges, we have to approximate */ + /* done like with ints and doubles. Creates a list of 2 fraction ranges */ + const GValue *min1 = gst_value_get_fraction_range_min (minuend); + const GValue *max2 = gst_value_get_fraction_range_max (minuend); + const GValue *max1 = gst_value_get_fraction_range_min (subtrahend); + const GValue *min2 = gst_value_get_fraction_range_max (subtrahend); + int cmp1, cmp2; + GValue v1 = { 0, }; + GValue v2 = { 0, }; + GValue *pv1, *pv2; /* yeah, hungarian! */ + + g_return_val_if_fail (min1 != NULL && max1 != NULL, FALSE); + g_return_val_if_fail (min2 != NULL && max2 != NULL, FALSE); + + cmp1 = gst_value_compare (max2, max1); + g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE); + if (cmp1 == GST_VALUE_LESS_THAN) + max1 = max2; + cmp1 = gst_value_compare (min1, min2); + g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE); + if (cmp1 == GST_VALUE_GREATER_THAN) + min2 = min1; + + cmp1 = gst_value_compare (min1, max1); + cmp2 = gst_value_compare (min2, max2); + + if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) { + pv1 = &v1; + pv2 = &v2; + } else if (cmp1 == GST_VALUE_LESS_THAN) { + pv1 = dest; + pv2 = NULL; + } else if (cmp2 == GST_VALUE_LESS_THAN) { + pv1 = NULL; + pv2 = dest; + } else { + return FALSE; + } + + if (cmp1 == GST_VALUE_LESS_THAN) { + g_value_init (pv1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range (pv1, min1, max1); + } + if (cmp2 == GST_VALUE_LESS_THAN) { + g_value_init (pv2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range (pv2, min2, max2); + } + + if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) { + gst_value_list_concat (dest, pv1, pv2); + g_value_unset (pv1); + g_value_unset (pv2); + } + return TRUE; +} + /************** * comparison * @@ -2857,6 +3268,55 @@ gst_value_fraction_multiply (GValue * product, const GValue * factor1, return TRUE; } +/** + * gst_value_fraction_subtract: + * @dest: a GValue initialized to #GST_TYPE_FRACTION + * @minued: a GValue initialized to #GST_TYPE_FRACTION + * @subtrahend: a GValue initialized to #GST_TYPE_FRACTION + * + * Subtracts the @subtrahend from the @minuend and sets @dest to the result. + * + * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise. + */ +gboolean +gst_value_fraction_subtract (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + gint gcd, n1, n2, d1, d2; + + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (minuend), FALSE); + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (subtrahend), FALSE); + + n1 = minuend->data[0].v_int; + n2 = subtrahend->data[0].v_int; + d1 = minuend->data[1].v_int; + d2 = subtrahend->data[1].v_int; + + if (n1 == 0) { + gst_value_set_fraction (dest, -n2, d2); + return TRUE; + } + if (n2 == 0) { + gst_value_set_fraction (dest, n1, d1); + return TRUE; + } + + gcd = gst_greatest_common_divisor (n1, d2); + n1 /= gcd; + d2 /= gcd; + gcd = gst_greatest_common_divisor (n2, d1); + n2 /= gcd; + d1 /= gcd; + + g_return_val_if_fail (n1 == 0 || G_MAXINT / ABS (n1) >= ABS (d2), FALSE); + g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (n2), FALSE); + g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (d2), FALSE); + + gst_value_set_fraction (dest, (n1 * d2) - (n2 * d1), d1 * d2); + + return TRUE; +} + static char * gst_value_serialize_fraction (const GValue * value) { @@ -2887,6 +3347,10 @@ gst_value_deserialize_fraction (GValue * dest, const char *s) gst_value_set_fraction (dest, num, den); return TRUE; } + if (s && sscanf (s, "%d", &num) == 1) { + gst_value_set_fraction (dest, num, 1); + return TRUE; + } return FALSE; } @@ -3221,6 +3685,19 @@ static const GTypeValueTable _gst_double_range_value_table = { FUNC_VALUE_GET_TYPE (double_range, "GstDoubleRange"); +static const GTypeValueTable _gst_fraction_range_value_table = { + gst_value_init_fraction_range, + gst_value_free_fraction_range, + gst_value_copy_fraction_range, + NULL, + "iiii", + gst_value_collect_fraction_range, + "pppp", + gst_value_lcopy_fraction_range +}; + +FUNC_VALUE_GET_TYPE (fraction_range, "GstFractionRange"); + static const GTypeValueTable _gst_value_list_value_table = { gst_value_init_list_or_array, gst_value_free_list_or_array, @@ -3328,6 +3805,18 @@ _gst_value_initialize (void) gst_value_register (&gst_value); } + { + static GstValueTable gst_value = { + 0, + gst_value_compare_fraction_range, + gst_value_serialize_fraction_range, + gst_value_deserialize_fraction_range, + }; + + gst_value.type = gst_fraction_range_get_type (); + gst_value_register (&gst_value); + } + { static GstValueTable gst_value = { 0, @@ -3433,6 +3922,8 @@ _gst_value_initialize (void) gst_value_transform_int_range_string); g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING, gst_value_transform_double_range_string); + g_value_register_transform_func (GST_TYPE_FRACTION_RANGE, G_TYPE_STRING, + gst_value_transform_fraction_range_string); g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING, gst_value_transform_list_string); g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_STRING, @@ -3460,6 +3951,11 @@ _gst_value_initialize (void) GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range); gst_value_register_intersect_func (GST_TYPE_ARRAY, GST_TYPE_ARRAY, gst_value_intersect_array); + gst_value_register_intersect_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, + gst_value_intersect_fraction_fraction_range); + gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE, + GST_TYPE_FRACTION_RANGE, + gst_value_intersect_fraction_range_fraction_range); gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE, gst_value_subtract_int_int_range); @@ -3474,6 +3970,14 @@ _gst_value_initialize (void) gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range); + gst_value_register_subtract_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, + gst_value_subtract_fraction_fraction_range); + gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE, GST_TYPE_FRACTION, + gst_value_subtract_fraction_range_fraction); + gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE, + GST_TYPE_FRACTION_RANGE, + gst_value_subtract_fraction_range_fraction_range); + #if GLIB_CHECK_VERSION(2,8,0) /* see bug #317246, #64994, #65041 */ { @@ -3487,4 +3991,12 @@ _gst_value_initialize (void) gst_value_union_int_int_range); gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE, gst_value_union_int_range_int_range); + +#if 0 + /* Implement these if needed */ + gst_value_register_union_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, + gst_value_union_fraction_fraction_range); + gst_value_register_union_func (GST_TYPE_FRACTION_RANGE, + GST_TYPE_FRACTION_RANGE, gst_value_union_fraction_range_fraction_range); +#endif } diff --git a/gst/gstvalue.h b/gst/gstvalue.h index cb2cbd3497..49d2ae77b8 100644 --- a/gst/gstvalue.h +++ b/gst/gstvalue.h @@ -108,6 +108,14 @@ G_BEGIN_DECLS */ #define GST_VALUE_HOLDS_DOUBLE_RANGE(x) (G_VALUE_HOLDS(x, gst_double_range_get_type ())) +/** + * GST_VALUE_HOLDS_FRACTION_RANGE: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_FRACTION_RANGE value. + */ +#define GST_VALUE_HOLDS_FRACTION_RANGE(x) (G_VALUE_HOLDS(x, gst_fraction_range_get_type ())) + /** * GST_VALUE_HOLDS_LIST: * @x: the #GValue to check @@ -183,6 +191,15 @@ G_BEGIN_DECLS */ #define GST_TYPE_DOUBLE_RANGE gst_double_range_get_type () +/** + * GST_TYPE_FRACTION_RANGE: + * + * a #GValue type that represents a GstFraction range + * + * Returns: the #GType of GstFractionRange + */ +#define GST_TYPE_FRACTION_RANGE gst_fraction_range_get_type () + /** * GST_TYPE_LIST: * @@ -362,6 +379,7 @@ struct _GstValueTable { GType gst_int_range_get_type (void); GType gst_double_range_get_type (void); +GType gst_fraction_range_get_type (void); GType gst_fourcc_get_type (void); GType gst_fraction_get_type (void); GType gst_value_list_get_type (void); @@ -434,6 +452,21 @@ int gst_value_get_fraction_denominator(const GValue *value); gboolean gst_value_fraction_multiply (GValue *product, const GValue *factor1, const GValue *factor2); +gboolean gst_value_fraction_subtract (GValue * dest, + const GValue * minuend, + const GValue * subtrahend); + +/* fraction range */ +void gst_value_set_fraction_range (GValue *value, + const GValue *start, + const GValue *end); +void gst_value_set_fraction_range_full (GValue *value, + int numerator_start, + int denominator_start, + int numerator_end, + int denominator_end); +const GValue *gst_value_get_fraction_range_min (const GValue *value); +const GValue *gst_value_get_fraction_range_max (const GValue *value); /* date */ G_CONST_RETURN GDate * diff --git a/tests/check/gst/capslist.h b/tests/check/gst/capslist.h index 8b84acafc9..894a905b39 100644 --- a/tests/check/gst/capslist.h +++ b/tests/check/gst/capslist.h @@ -15,6 +15,10 @@ static const gchar *caps_list[] = { "video/x-raw-rgb, bpp = (int) 32, depth = (int) 24, endianness = (int) BIG_ENDIAN, red_mask = (int) 0x000000FF, framerate = (double) [ 0, max ]", "video/x-raw-rgb, bpp = (int) 32, depth = (int) 24, endianness = (int) BIG_ENDIAN, red_mask = (int) 0xFF000000, framerate = (double) [ 0, max ]", "video/x-raw-rgb,\\ bpp=(int)32", + "test/gst-fraction, fraction = (fraction) 1/8", + "test/gst-fraction-range, fraction = (fraction) [ 1/3, 1/4 ]", + "test/gst-fraction-range, fraction = (fraction) { [ 1/3, 1/4 ], 1/8 }", + "test/gst-fraction-range, fraction = (fraction) { [ 1/3, 1/4 ], [ 1/8, 2/8 ] }", "ANY", "EMPTY" }; diff --git a/tests/check/gst/gstcaps.c b/tests/check/gst/gstcaps.c index 1df100b6d0..75e81de95f 100644 --- a/tests/check/gst/gstcaps.c +++ b/tests/check/gst/gstcaps.c @@ -128,14 +128,14 @@ GST_START_TEST (test_static_caps) GST_END_TEST; static const gchar non_simple_caps_string[] = - "video/x-raw-yuv, format=(fourcc)I420, framerate=(double)[ 1, 100 ], " + "video/x-raw-yuv, format=(fourcc)I420, framerate=(fraction)[ 1/100, 100 ], " "width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-yuv, " - "format=(fourcc)YUY2, framerate=(double)[ 1, 100 ], width=(int)[ 16, 4096 ], " + "format=(fourcc)YUY2, framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], " "height=(int)[ 16, 4096 ]; video/x-raw-rgb, bpp=(int)8, depth=(int)8, " - "endianness=(int)1234, framerate=(double)[ 1, 100 ], width=(int)[ 16, 4096 ], " + "endianness=(int)1234, framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], " "height=(int)[ 16, 4096 ]; video/x-raw-yuv, " "format=(fourcc){ I420, YUY2, YV12 }, width=(int)[ 16, 4096 ], " - "height=(int)[ 16, 4096 ], framerate=(double)[ 1, 100 ]"; + "height=(int)[ 16, 4096 ], framerate=(fraction)[ 1/100, 100 ]"; static gboolean check_fourcc_list (const GValue * format_value) @@ -193,11 +193,11 @@ GST_START_TEST (test_simplify) /* check simplified caps, should be: * * video/x-raw-rgb, bpp=(int)8, depth=(int)8, endianness=(int)1234, - * framerate=(double)[ 1, 100 ], width=(int)[ 16, 4096 ], + * framerate=(fraction)[ 1/100, 100 ], width=(int)[ 16, 4096 ], * height=(int)[ 16, 4096 ]; * video/x-raw-yuv, format=(fourcc){ YV12, YUY2, I420 }, * width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], - * framerate=(double)[ 1, 100 ] + * framerate=(fraction)[ 1/100, 100 ] */ fail_unless (gst_caps_get_size (caps) == 2); s1 = gst_caps_get_structure (caps, 0); @@ -218,7 +218,8 @@ GST_START_TEST (test_simplify) const GValue *framerate_value; const GValue *width_value; const GValue *height_value; - gdouble min_fps, max_fps; + const GValue *val_fps; + GValue test_fps = { 0, }; gint bpp, depth, endianness; gint min_width, max_width; gint min_height, max_height; @@ -232,12 +233,20 @@ GST_START_TEST (test_simplify) fail_unless (gst_structure_get_int (s1, "endianness", &endianness)); fail_unless (endianness == G_LITTLE_ENDIAN); + g_value_init (&test_fps, GST_TYPE_FRACTION); framerate_value = gst_structure_get_value (s1, "framerate"); fail_unless (framerate_value != NULL); - fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (framerate_value)); - min_fps = gst_value_get_double_range_min (framerate_value); - max_fps = gst_value_get_double_range_max (framerate_value); - fail_unless (min_fps == 1.0 && max_fps == 100.0); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (framerate_value)); + + val_fps = gst_value_get_fraction_range_min (framerate_value); + gst_value_set_fraction (&test_fps, 1, 100); + fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL); + + val_fps = gst_value_get_fraction_range_max (framerate_value); + gst_value_set_fraction (&test_fps, 100, 1); + fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL); + + g_value_unset (&test_fps); width_value = gst_structure_get_value (s1, "width"); fail_unless (width_value != NULL); @@ -260,7 +269,8 @@ GST_START_TEST (test_simplify) const GValue *format_value; const GValue *width_value; const GValue *height_value; - gdouble min_fps, max_fps; + const GValue *val_fps; + GValue test_fps = { 0, }; gint min_width, max_width; gint min_height, max_height; @@ -270,12 +280,20 @@ GST_START_TEST (test_simplify) fail_unless (gst_value_list_get_size (format_value) == 3); fail_unless (check_fourcc_list (format_value) == TRUE); + g_value_init (&test_fps, GST_TYPE_FRACTION); framerate_value = gst_structure_get_value (s2, "framerate"); fail_unless (framerate_value != NULL); - fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (framerate_value)); - min_fps = gst_value_get_double_range_min (framerate_value); - max_fps = gst_value_get_double_range_max (framerate_value); - fail_unless (min_fps == 1.0 && max_fps == 100.0); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (framerate_value)); + + val_fps = gst_value_get_fraction_range_min (framerate_value); + gst_value_set_fraction (&test_fps, 1, 100); + fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL); + + val_fps = gst_value_get_fraction_range_max (framerate_value); + gst_value_set_fraction (&test_fps, 100, 1); + fail_unless (gst_value_compare (&test_fps, val_fps) == GST_VALUE_EQUAL); + + g_value_unset (&test_fps); width_value = gst_structure_get_value (s2, "width"); fail_unless (width_value != NULL); diff --git a/tests/check/gst/gstvalue.c b/tests/check/gst/gstvalue.c index 61774d32ba..1da8e06295 100644 --- a/tests/check/gst/gstvalue.c +++ b/tests/check/gst/gstvalue.c @@ -435,6 +435,7 @@ GST_START_TEST (test_value_compare) fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL); g_value_unset (&value1); g_value_unset (&value2); + } GST_END_TEST; @@ -958,6 +959,280 @@ GST_START_TEST (test_value_subtract_double) GST_END_TEST; +/* Test arithmetic subtraction of fractions */ +GST_START_TEST (test_value_subtract_fraction) +{ + GValue result = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + + /* Subtract 1/4 from 1/2 */ + g_value_init (&src1, GST_TYPE_FRACTION); + g_value_init (&src2, GST_TYPE_FRACTION); + g_value_init (&result, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 1, 2); + gst_value_set_fraction (&src2, 1, 4); + fail_unless (gst_value_fraction_subtract (&result, &src1, &src2) == TRUE); + fail_unless (gst_value_get_fraction_numerator (&result) == 1); + fail_unless (gst_value_get_fraction_denominator (&result) == 4); + + g_value_unset (&src1); + g_value_unset (&src2); + g_value_unset (&result); + + /* Subtract 1/12 from 7/8 */ + g_value_init (&src1, GST_TYPE_FRACTION); + g_value_init (&src2, GST_TYPE_FRACTION); + g_value_init (&result, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 7, 8); + gst_value_set_fraction (&src2, 1, 12); + fail_unless (gst_value_fraction_subtract (&result, &src1, &src2) == TRUE); + fail_unless (gst_value_get_fraction_numerator (&result) == 19); + fail_unless (gst_value_get_fraction_denominator (&result) == 24); + + g_value_unset (&src1); + g_value_unset (&src2); + g_value_unset (&result); +} + +GST_END_TEST; + +/* Test set subtraction operations on fraction ranges */ +GST_START_TEST (test_value_subtract_fraction_range) +{ + GValue dest = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + GValue cmp = { 0 }; + const GValue *tmp; + gboolean ret; + + /* Value for tests */ + g_value_init (&cmp, GST_TYPE_FRACTION); + + /* fraction <-> fraction + */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION); + gst_value_set_fraction (&src2, 20, 1); + gst_value_set_fraction (&src1, 10, 1); + + /* 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); + + /* fraction <-> fraction_range + */ + + /* would yield an empty set */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 0, 1, 20, 1); + 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_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 0, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 1, empty set */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 1, 20, 1); + 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_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* case 2, valid set */ + g_value_init (&src1, GST_TYPE_FRACTION); + gst_value_set_fraction (&src1, 0, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 1, 20, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_FRACTION (&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_FRACTION_RANGE (&dest) == TRUE); + fail_unless (gst_value_compare (&dest, &src2) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* fraction_range <-> fraction_range + */ + + /* same range, empty set */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 2, 20, 2); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 2, 20, 2); + 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_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 2, 10, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 30, 2, 40, 2); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 5, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 15, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* completely overlapping ranges */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 1, 20, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 10, 1, 30, 1); + 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_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 30, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* partially overlapping ranges */ + g_value_init (&src1, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 1, 20, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 15, 1, 30, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 15, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (&dest) == TRUE); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 30, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest), + &cmp) == GST_VALUE_EQUAL); + 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_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src1, 10, 1, 30, 1); + g_value_init (&src2, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&src2, 15, 1, 20, 1); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE); + /* 1st list entry */ + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (tmp) == TRUE); + gst_value_set_fraction (&cmp, 10, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (tmp), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 15, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (tmp), + &cmp) == GST_VALUE_EQUAL); + /* 2nd list entry */ + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (tmp) == TRUE); + gst_value_set_fraction (&cmp, 20, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_min (tmp), + &cmp) == GST_VALUE_EQUAL); + gst_value_set_fraction (&cmp, 30, 1); + fail_unless (gst_value_compare (gst_value_get_fraction_range_max (tmp), + &cmp) == GST_VALUE_EQUAL); + 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); + + g_value_unset (&cmp); +} + +GST_END_TEST; + GST_START_TEST (test_date) { GstStructure *s; @@ -1017,6 +1292,59 @@ GST_START_TEST (test_date) GST_END_TEST; +GST_START_TEST (test_fraction_range) +{ + GValue range = { 0, }; + GValue start = { 0, }, end = { + 0,}; + GValue src = { 0, }, dest = { + 0,}; + GValue range2 = { 0, }; + + g_value_init (&range, GST_TYPE_FRACTION_RANGE); + g_value_init (&range2, GST_TYPE_FRACTION_RANGE); + g_value_init (&start, GST_TYPE_FRACTION); + g_value_init (&end, GST_TYPE_FRACTION); + g_value_init (&src, GST_TYPE_FRACTION); + + gst_value_set_fraction (&src, 1, 2); + + /* Check that a intersection of fraction & range = fraction */ + gst_value_set_fraction (&start, 1, 4); + gst_value_set_fraction (&end, 2, 3); + gst_value_set_fraction_range (&range, &start, &end); + + fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION); + fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL); + + /* Check that a intersection selects the overlapping range */ + gst_value_set_fraction (&start, 1, 3); + gst_value_set_fraction (&end, 2, 3); + gst_value_set_fraction_range (&range2, &start, &end); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE); + + gst_value_set_fraction_range (&range2, &start, &end); + fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL); + + /* Check that non intersection ranges don't intersect */ + gst_value_set_fraction (&start, 4, 2); + gst_value_set_fraction (&end, 5, 2); + gst_value_set_fraction_range (&range2, &start, &end); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE); + + g_value_unset (&start); + g_value_unset (&end); + g_value_unset (&range); + g_value_unset (&range2); + g_value_unset (&src); +} + +GST_END_TEST; + Suite * gst_value_suite (void) { @@ -1037,7 +1365,10 @@ gst_value_suite (void) 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); + tcase_add_test (tc_chain, test_value_subtract_fraction); + tcase_add_test (tc_chain, test_value_subtract_fraction_range); tcase_add_test (tc_chain, test_date); + tcase_add_test (tc_chain, test_fraction_range); return s; }