diff --git a/ChangeLog b/ChangeLog index e8d3660da8..7c8c3e5813 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2004-03-31 David Schleef + + * gst/gstvalue.c: (gst_value_union_int_int_range), + (gst_value_union_int_range_int_range), (gst_value_can_union), + (gst_value_union), (_gst_value_initialize): Add some union + implementations. We didn't have any previously. + * testsuite/caps/Makefile.am: + * testsuite/caps/audioscale.c: (gst_audioscale_expand_value), + (gst_audioscale_getcaps), (test_caps), (main): A little test + that is the same as the caps manipulation in audioscale. + 2004-03-30 Benjamin Otte * docs/faq/general.xml: diff --git a/gst/gstvalue.c b/gst/gstvalue.c index 774c8a5d9d..80ad010a4b 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -1009,6 +1009,46 @@ gst_value_deserialize_string (GValue * dest, const char *s) /*************************************/ /* unions */ +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; +} + +static gboolean +gst_value_union_int_range_int_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + 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); + + if (min <= max) { + g_value_init (dest, GST_TYPE_INT_RANGE); + gst_value_set_int_range (dest, + MIN (src1->data[0].v_int, src2->data[0].v_int), + MAX (src1->data[1].v_int, src2->data[1].v_int)); + return TRUE; + } + + return FALSE; +} + /*************************************/ /* intersection */ @@ -1226,6 +1266,9 @@ gst_value_can_union (const GValue * value1, const GValue * value2) if (union_info->type1 == G_VALUE_TYPE (value1) && union_info->type2 == G_VALUE_TYPE (value2)) return TRUE; + if (union_info->type1 == G_VALUE_TYPE (value2) && + union_info->type2 == G_VALUE_TYPE (value1)) + return TRUE; } return FALSE; @@ -1251,7 +1294,15 @@ gst_value_union (GValue * dest, const GValue * value1, const GValue * value2) union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i); if (union_info->type1 == G_VALUE_TYPE (value1) && union_info->type2 == G_VALUE_TYPE (value2)) { - return union_info->func (dest, value1, value2); + if (union_info->func (dest, value1, value2)) { + return TRUE; + } + } + if (union_info->type1 == G_VALUE_TYPE (value2) && + union_info->type2 == G_VALUE_TYPE (value1)) { + if (union_info->func (dest, value2, value1)) { + return TRUE; + } } } @@ -1641,4 +1692,9 @@ _gst_value_initialize (void) gst_value_intersect_double_double_range); gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE, GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range); + + gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE, + 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); } diff --git a/tests/old/testsuite/caps/Makefile.am b/tests/old/testsuite/caps/Makefile.am index 10d217aa1a..a0dd4a4105 100644 --- a/tests/old/testsuite/caps/Makefile.am +++ b/tests/old/testsuite/caps/Makefile.am @@ -12,7 +12,8 @@ tests_pass = \ intersect2 \ caps \ value_compare \ - value_intersect + value_intersect \ + audioscale tests_fail = diff --git a/tests/old/testsuite/caps/audioscale.c b/tests/old/testsuite/caps/audioscale.c new file mode 100644 index 0000000000..9b73dbd853 --- /dev/null +++ b/tests/old/testsuite/caps/audioscale.c @@ -0,0 +1,174 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* Element-Checklist-Version: 5 */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include + + +static void +gst_audioscale_expand_value (GValue * dest, const GValue * src) +{ + int rate_min, rate_max; + + if (G_VALUE_TYPE (src) == G_TYPE_INT || + G_VALUE_TYPE (src) == GST_TYPE_INT_RANGE) { + if (G_VALUE_TYPE (src) == G_TYPE_INT) { + rate_min = g_value_get_int (src); + rate_max = rate_min; + } else { + rate_min = gst_value_get_int_range_min (src); + rate_max = gst_value_get_int_range_max (src); + } + + rate_min /= 2; + if (rate_min < 1) + rate_min = 1; + if (rate_max < G_MAXINT / 2) { + rate_max *= 2; + } else { + rate_max = G_MAXINT; + } + + g_value_init (dest, GST_TYPE_INT_RANGE); + gst_value_set_int_range (dest, rate_min, rate_max); + return; + } + + if (G_VALUE_TYPE (src) == GST_TYPE_LIST) { + int i; + + g_value_init (dest, GST_TYPE_LIST); + for (i = 0; i < gst_value_list_get_size (src); i++) { + const GValue *s = gst_value_list_get_value (src, i); + GValue d = { 0 }; + int j; + + gst_audioscale_expand_value (&d, s); + + for (j = 0; j < gst_value_list_get_size (dest); j++) { + const GValue *s2 = gst_value_list_get_value (dest, j); + GValue d2 = { 0 }; + + gst_value_union (&d2, &d, s2); + if (G_VALUE_TYPE (&d2) == GST_TYPE_INT_RANGE) { + g_value_unset ((GValue *) s2); + gst_value_init_and_copy ((GValue *) s2, &d2); + break; + } + g_value_unset (&d2); + } + if (j == gst_value_list_get_size (dest)) { + gst_value_list_append_value (dest, &d); + } + g_value_unset (&d); + } + + if (gst_value_list_get_size (dest) == 1) { + const GValue *s = gst_value_list_get_value (dest, 0); + GValue d = { 0 }; + + gst_value_init_and_copy (&d, s); + g_value_unset (dest); + gst_value_init_and_copy (dest, &d); + g_value_unset (&d); + } + + return; + } + + GST_ERROR ("unexpected value type"); +} + +static GstCaps * +gst_audioscale_getcaps (const GstCaps * othercaps) +{ + GstCaps *caps; + int i; + + caps = gst_caps_copy (othercaps); + + /* we do this hack, because the audioscale lib doesn't handle + * rate conversions larger than a factor of 2 */ + for (i = 0; i < gst_caps_get_size (caps); i++) { + GstStructure *structure = gst_caps_get_structure (caps, i); + const GValue *value; + GValue dest = { 0 }; + + value = gst_structure_get_value (structure, "rate"); + if (value == NULL) { + GST_ERROR ("caps structure doesn't have required rate field"); + return NULL; + } + + gst_audioscale_expand_value (&dest, value); + + gst_structure_set_value (structure, "rate", &dest); + } + + return caps; +} + + +void +test_caps (const char *s) +{ + GstCaps *caps; + GstCaps *caps2; + char *s2; + + caps = gst_caps_from_string (s); + caps2 = gst_audioscale_getcaps (caps); + s2 = gst_caps_to_string (caps2); + + g_print ("original: %s\nfiltered: %s\n\n", s, s2); + + g_free (s2); + gst_caps_free (caps); + gst_caps_free (caps2); +} + + +int +main (int argc, char *argv[]) +{ + + gst_init (&argc, &argv); + + test_caps ("audio/x-raw-int, rate=(int)1"); + test_caps ("audio/x-raw-int, rate=(int)10"); + test_caps ("audio/x-raw-int, rate=(int)100"); + test_caps ("audio/x-raw-int, rate=(int)10000"); + test_caps ("audio/x-raw-int, rate=(int)2000000000"); + + test_caps ("audio/x-raw-int, rate=(int)[1,100]"); + test_caps ("audio/x-raw-int, rate=(int)[1000,40000]"); + + test_caps ("audio/x-raw-int, rate=(int){1,100}"); + test_caps ("audio/x-raw-int, rate=(int){100,200,300}"); + test_caps ("audio/x-raw-int, rate=(int){[100,200],1000}"); + + return 0; +} diff --git a/testsuite/caps/Makefile.am b/testsuite/caps/Makefile.am index 10d217aa1a..a0dd4a4105 100644 --- a/testsuite/caps/Makefile.am +++ b/testsuite/caps/Makefile.am @@ -12,7 +12,8 @@ tests_pass = \ intersect2 \ caps \ value_compare \ - value_intersect + value_intersect \ + audioscale tests_fail = diff --git a/testsuite/caps/audioscale.c b/testsuite/caps/audioscale.c new file mode 100644 index 0000000000..9b73dbd853 --- /dev/null +++ b/testsuite/caps/audioscale.c @@ -0,0 +1,174 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* Element-Checklist-Version: 5 */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include + + +static void +gst_audioscale_expand_value (GValue * dest, const GValue * src) +{ + int rate_min, rate_max; + + if (G_VALUE_TYPE (src) == G_TYPE_INT || + G_VALUE_TYPE (src) == GST_TYPE_INT_RANGE) { + if (G_VALUE_TYPE (src) == G_TYPE_INT) { + rate_min = g_value_get_int (src); + rate_max = rate_min; + } else { + rate_min = gst_value_get_int_range_min (src); + rate_max = gst_value_get_int_range_max (src); + } + + rate_min /= 2; + if (rate_min < 1) + rate_min = 1; + if (rate_max < G_MAXINT / 2) { + rate_max *= 2; + } else { + rate_max = G_MAXINT; + } + + g_value_init (dest, GST_TYPE_INT_RANGE); + gst_value_set_int_range (dest, rate_min, rate_max); + return; + } + + if (G_VALUE_TYPE (src) == GST_TYPE_LIST) { + int i; + + g_value_init (dest, GST_TYPE_LIST); + for (i = 0; i < gst_value_list_get_size (src); i++) { + const GValue *s = gst_value_list_get_value (src, i); + GValue d = { 0 }; + int j; + + gst_audioscale_expand_value (&d, s); + + for (j = 0; j < gst_value_list_get_size (dest); j++) { + const GValue *s2 = gst_value_list_get_value (dest, j); + GValue d2 = { 0 }; + + gst_value_union (&d2, &d, s2); + if (G_VALUE_TYPE (&d2) == GST_TYPE_INT_RANGE) { + g_value_unset ((GValue *) s2); + gst_value_init_and_copy ((GValue *) s2, &d2); + break; + } + g_value_unset (&d2); + } + if (j == gst_value_list_get_size (dest)) { + gst_value_list_append_value (dest, &d); + } + g_value_unset (&d); + } + + if (gst_value_list_get_size (dest) == 1) { + const GValue *s = gst_value_list_get_value (dest, 0); + GValue d = { 0 }; + + gst_value_init_and_copy (&d, s); + g_value_unset (dest); + gst_value_init_and_copy (dest, &d); + g_value_unset (&d); + } + + return; + } + + GST_ERROR ("unexpected value type"); +} + +static GstCaps * +gst_audioscale_getcaps (const GstCaps * othercaps) +{ + GstCaps *caps; + int i; + + caps = gst_caps_copy (othercaps); + + /* we do this hack, because the audioscale lib doesn't handle + * rate conversions larger than a factor of 2 */ + for (i = 0; i < gst_caps_get_size (caps); i++) { + GstStructure *structure = gst_caps_get_structure (caps, i); + const GValue *value; + GValue dest = { 0 }; + + value = gst_structure_get_value (structure, "rate"); + if (value == NULL) { + GST_ERROR ("caps structure doesn't have required rate field"); + return NULL; + } + + gst_audioscale_expand_value (&dest, value); + + gst_structure_set_value (structure, "rate", &dest); + } + + return caps; +} + + +void +test_caps (const char *s) +{ + GstCaps *caps; + GstCaps *caps2; + char *s2; + + caps = gst_caps_from_string (s); + caps2 = gst_audioscale_getcaps (caps); + s2 = gst_caps_to_string (caps2); + + g_print ("original: %s\nfiltered: %s\n\n", s, s2); + + g_free (s2); + gst_caps_free (caps); + gst_caps_free (caps2); +} + + +int +main (int argc, char *argv[]) +{ + + gst_init (&argc, &argv); + + test_caps ("audio/x-raw-int, rate=(int)1"); + test_caps ("audio/x-raw-int, rate=(int)10"); + test_caps ("audio/x-raw-int, rate=(int)100"); + test_caps ("audio/x-raw-int, rate=(int)10000"); + test_caps ("audio/x-raw-int, rate=(int)2000000000"); + + test_caps ("audio/x-raw-int, rate=(int)[1,100]"); + test_caps ("audio/x-raw-int, rate=(int)[1000,40000]"); + + test_caps ("audio/x-raw-int, rate=(int){1,100}"); + test_caps ("audio/x-raw-int, rate=(int){100,200,300}"); + test_caps ("audio/x-raw-int, rate=(int){[100,200],1000}"); + + return 0; +}