gstvalue: add hashing
Will be used to implement the Hash trait in gstreamer-rs, see https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1639 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8518>
This commit is contained in:
parent
bde69a4fab
commit
4e65d16bfc
@ -11,6 +11,6 @@ variables:
|
||||
|
||||
CHECKS_TAG: '2025-02-04.0'
|
||||
|
||||
ABI_CHECK_TAG: '2025-03-13.0'
|
||||
ABI_CHECK_TAG: '2025-04-01.0'
|
||||
|
||||
WINDOWS_TAG: '2025-02-23.0'
|
||||
|
@ -51890,6 +51890,24 @@ or GST_VALUE_UNORDERED</doc>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</callback>
|
||||
<callback name="ValueHashFunc" c:type="GstValueHashFunc" version="1.28">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.h">Used by gst_value_hash() to calculate a hash of @value.</doc>
|
||||
<source-position filename="../subprojects/gstreamer/gst/gstvalue.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.h">%TRUE, or %FALSE if @value cannot be hashed.</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<parameter name="value" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.h">a #GValue</doc>
|
||||
<type name="GObject.Value" c:type="const GValue*"/>
|
||||
</parameter>
|
||||
<parameter name="res" direction="out" caller-allocates="0" transfer-ownership="full">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.h">a location to store the hash value</doc>
|
||||
<type name="guint" c:type="guint*"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</callback>
|
||||
<class name="ValueList" c:symbol-prefix="value_list" glib:type-name="GstValueList" glib:get-type="gst_value_list_get_type" glib:fundamental="1">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.h">A fundamental type that describes an unordered list of #GValue</doc>
|
||||
<function name="append_and_take_value" c:identifier="gst_value_list_append_and_take_value" version="1.2">
|
||||
@ -52083,8 +52101,12 @@ Free-function: g_free</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.h">a #GstValueDeserializeWithPSpecFunc</doc>
|
||||
<type name="ValueDeserializeWithPSpecFunc" c:type="GstValueDeserializeWithPSpecFunc"/>
|
||||
</field>
|
||||
<field name="hash" version="1.28" writable="1">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.h">a #GstValueHashFunc</doc>
|
||||
<type name="ValueHashFunc" c:type="GstValueHashFunc"/>
|
||||
</field>
|
||||
<field name="_gst_reserved" readable="0" private="1">
|
||||
<array zero-terminated="0" fixed-size="3">
|
||||
<array zero-terminated="0" fixed-size="2">
|
||||
<type name="gpointer" c:type="gpointer"/>
|
||||
</array>
|
||||
</field>
|
||||
@ -58598,6 +58620,25 @@ a reference to @v.</doc>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="value_hash" c:identifier="gst_value_hash" version="1.28">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.c">Compute a hash value of @value.
|
||||
#GValue considered as equals by gst_value_compare() will have the same hash value.</doc>
|
||||
<source-position filename="../subprojects/gstreamer/gst/gstvalue.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.c">%TRUE, or %FALSE if @value cannot be hashed.</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<parameter name="value" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.c">a #GValue to hash</doc>
|
||||
<type name="GObject.Value" c:type="const GValue*"/>
|
||||
</parameter>
|
||||
<parameter name="res" direction="out" caller-allocates="0" transfer-ownership="full">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.c">a location to store the hash value</doc>
|
||||
<type name="guint" c:type="guint*"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="value_init_and_copy" c:identifier="gst_value_init_and_copy">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.c">Initialises the target value to be of the same type as source and then copies
|
||||
the contents from source to target.</doc>
|
||||
|
@ -3219,6 +3219,7 @@ gst_value_serialize_tag_list (const GValue * value)
|
||||
static gint
|
||||
compare_buffer (GstBuffer * buf1, GstBuffer * buf2)
|
||||
{
|
||||
/* keep this implementation synced with gst_hash_buffer() */
|
||||
gsize size1, size2;
|
||||
GstMapInfo info1, info2;
|
||||
gint result, mret;
|
||||
@ -3355,6 +3356,7 @@ wrong_char:
|
||||
static gint
|
||||
gst_value_compare_sample (const GValue * value1, const GValue * value2)
|
||||
{
|
||||
/* keep this implementation synced with gst_value_hash_sample() */
|
||||
GstBuffer *buf1 = gst_sample_get_buffer (gst_value_get_sample (value1));
|
||||
GstBuffer *buf2 = gst_sample_get_buffer (gst_value_get_sample (value2));
|
||||
|
||||
@ -6139,7 +6141,8 @@ gst_value_compare (const GValue * value1, const GValue * value2)
|
||||
value2_is_list = G_VALUE_TYPE (value2) == GST_TYPE_LIST;
|
||||
|
||||
/* Special cases: lists and scalar values ("{ 1 }" and "1" are equal),
|
||||
as well as lists and ranges ("{ 1, 2 }" and "[ 1, 2 ]" are equal) */
|
||||
as well as lists and ranges ("{ 1, 2 }" and "[ 1, 2 ]" are equal).
|
||||
Make sure to update gst_value_hash() when adding new special cases. */
|
||||
if (value1_is_list && !value2_is_list) {
|
||||
gint i, n, ret;
|
||||
|
||||
@ -8059,6 +8062,548 @@ gst_value_compare_flagset (const GValue * value1, const GValue * value2)
|
||||
return GST_VALUE_UNORDERED;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_int (const GValue * v, guint * res)
|
||||
{
|
||||
gint i = g_value_get_int (v);
|
||||
*res = g_int_hash ((gconstpointer) & i);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_int64 (const GValue * v, guint * res)
|
||||
{
|
||||
gint64 i = g_value_get_int64 (v);
|
||||
*res = g_int64_hash ((gconstpointer) & i);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_long (const GValue * v, guint * res)
|
||||
{
|
||||
glong l = g_value_get_long (v);
|
||||
|
||||
#if GLIB_SIZEOF_LONG == 4
|
||||
*res = g_int_hash ((gconstpointer) & l);
|
||||
#else
|
||||
*res = g_int64_hash ((gconstpointer) & l);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_uint (const GValue * v, guint * res)
|
||||
{
|
||||
guint u = g_value_get_uint (v);
|
||||
*res = g_int_hash ((gconstpointer) & u);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_uint64 (const GValue * v, guint * res)
|
||||
{
|
||||
guint64 u = g_value_get_uint64 (v);
|
||||
*res = g_int64_hash ((gconstpointer) & u);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_ulong (const GValue * v, guint * res)
|
||||
{
|
||||
gulong u = g_value_get_ulong (v);
|
||||
*res = g_double_hash ((gconstpointer) & u);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_uchar (const GValue * v, guint * res)
|
||||
{
|
||||
guchar u = g_value_get_uchar (v);
|
||||
gint i = u;
|
||||
*res = g_int_hash ((gconstpointer) & i);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_gtype (const GValue * v, guint * res)
|
||||
{
|
||||
GType t = g_value_get_gtype (v);
|
||||
|
||||
#if GLIB_SIZEOF_SIZE_T == 4
|
||||
*res = g_int_hash ((gconstpointer) & t);
|
||||
#else
|
||||
*res = g_int64_hash ((gconstpointer) & t);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_double (const GValue * v, guint * res)
|
||||
{
|
||||
gdouble d = g_value_get_double (v);
|
||||
*res = g_double_hash ((gconstpointer) & d);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_float (const GValue * v, guint * res)
|
||||
{
|
||||
gfloat f = g_value_get_float (v);
|
||||
*res = g_int_hash ((gconstpointer) & f);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_string (const GValue * v, guint * res)
|
||||
{
|
||||
const gchar *s = g_value_get_string (v);
|
||||
*res = g_str_hash (s);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_boolean (const GValue * v, guint * res)
|
||||
{
|
||||
gboolean b = g_value_get_boolean (v);
|
||||
*res = b ? 1 : 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_enum (const GValue * v, guint * res)
|
||||
{
|
||||
gint e = g_value_get_enum (v);
|
||||
*res = g_int_hash ((gconstpointer) & e);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_gflags (const GValue * v, guint * res)
|
||||
{
|
||||
guint f = g_value_get_flags (v);
|
||||
*res = g_int_hash ((gconstpointer) & f);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* helper to combine hash when hashing ordered container */
|
||||
static void
|
||||
combine_hash_ordered (guint * hash, guint value_hash)
|
||||
{
|
||||
/* perform a rotating shift to account for the position in the container */
|
||||
*hash = ((*hash << 5) | (*hash >> 27)) ^ value_hash;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_int_range (const GValue * v, guint * res)
|
||||
{
|
||||
gint min = gst_value_get_int_range_min (v);
|
||||
gint max = gst_value_get_int_range_max (v);
|
||||
gint step = gst_value_get_int_range_step (v);
|
||||
gint i;
|
||||
|
||||
*res = 0;
|
||||
/* range and list are considered as equal if they contain the same elements,
|
||||
so they should have the same hash. Lists are not ordered so do not account
|
||||
for element position when hashing. */
|
||||
for (i = min; i <= max; i += step) {
|
||||
*res ^= g_int_hash ((gconstpointer) & i);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_int64_range (const GValue * v, guint * res)
|
||||
{
|
||||
gint64 min = gst_value_get_int64_range_min (v);
|
||||
gint64 max = gst_value_get_int64_range_max (v);
|
||||
gint64 step = gst_value_get_int64_range_step (v);
|
||||
gint64 i;
|
||||
|
||||
*res = 0;
|
||||
for (i = min; i <= max; i += step) {
|
||||
*res ^= g_int64_hash ((gconstpointer) & i);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_double_range (const GValue * v, guint * res)
|
||||
{
|
||||
gdouble min = gst_value_get_double_range_min (v);
|
||||
gdouble max = gst_value_get_double_range_max (v);
|
||||
|
||||
*res = g_double_hash ((gconstpointer) & min) ^ g_double_hash ((gconstpointer)
|
||||
& max);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_g_value_array (const GValue * v, guint * res)
|
||||
{
|
||||
guint i = 0;
|
||||
GValueArray *array = g_value_get_boxed (v);
|
||||
|
||||
*res = 0;
|
||||
for (i = 0; i < array->n_values; i++) {
|
||||
guint value_hash;
|
||||
if (!gst_value_hash (&array->values[i], &value_hash))
|
||||
return FALSE;
|
||||
combine_hash_ordered (res, value_hash);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_hash_buffer (GstBuffer * buf, guint * res)
|
||||
{
|
||||
GstBufferMapInfo map;
|
||||
guint i;
|
||||
|
||||
*res = 0;
|
||||
|
||||
if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < map.size; i++) {
|
||||
combine_hash_ordered (res, map.data[i]);
|
||||
}
|
||||
|
||||
gst_buffer_unmap (buf, &map);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_buffer (const GValue * v, guint * res)
|
||||
{
|
||||
GstBuffer *buf = gst_value_get_buffer (v);
|
||||
|
||||
/* compare_buffer() only compares the buffer content */
|
||||
return gst_hash_buffer (buf, res);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_sample (const GValue * v, guint * res)
|
||||
{
|
||||
GstSample *sample = gst_value_get_sample (v);
|
||||
GstBuffer *buf = gst_sample_get_buffer (sample);
|
||||
|
||||
/* gst_value_compare_sample() only compares buffers */
|
||||
return gst_hash_buffer (buf, res);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_fraction (const GValue * v, guint * res)
|
||||
{
|
||||
gint num = gst_value_get_fraction_numerator (v);
|
||||
gint den = gst_value_get_fraction_denominator (v);
|
||||
gfloat div = ((gfloat) num) / ((gfloat) den);
|
||||
|
||||
*res = g_int_hash ((gconstpointer) & div);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_fraction_range (const GValue * v, guint * res)
|
||||
{
|
||||
const GValue *min = gst_value_get_fraction_range_min (v);
|
||||
const GValue *max = gst_value_get_fraction_range_max (v);
|
||||
gint num, den;
|
||||
gfloat div;
|
||||
|
||||
num = gst_value_get_fraction_numerator (min);
|
||||
den = gst_value_get_fraction_denominator (min);
|
||||
div = ((gfloat) num) / ((gfloat) den);
|
||||
*res = g_int_hash ((gconstpointer) & div);
|
||||
|
||||
num = gst_value_get_fraction_numerator (max);
|
||||
den = gst_value_get_fraction_denominator (max);
|
||||
div = ((gfloat) num) / ((gfloat) den);
|
||||
*res ^= g_int_hash ((gconstpointer) & div);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
hash_structure_foreach (const GstIdStr * fieldname,
|
||||
const GValue * value, gpointer user_data)
|
||||
{
|
||||
gint *hash = user_data;
|
||||
guint value_hash;
|
||||
|
||||
*hash ^= g_str_hash (gst_id_str_as_str (fieldname));
|
||||
if (!gst_value_hash (value, &value_hash))
|
||||
return FALSE;
|
||||
*hash ^= value_hash;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_hash_structure (const GstStructure * s, guint * res)
|
||||
{
|
||||
*res = g_str_hash (gst_structure_get_name (s));
|
||||
return gst_structure_foreach_id_str (s, hash_structure_foreach, res);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_structure (const GValue * v, guint * res)
|
||||
{
|
||||
const GstStructure *s = gst_value_get_structure (v);
|
||||
|
||||
return gst_hash_structure (s, res);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_hash_caps_features (const GstCapsFeatures * features, guint * res)
|
||||
{
|
||||
guint i;
|
||||
|
||||
*res = 0;
|
||||
|
||||
for (i = 0; i < gst_caps_features_get_size (features); i++) {
|
||||
const gchar *feature = gst_caps_features_get_nth (features, i);
|
||||
*res ^= g_str_hash (feature);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_caps_features (const GValue * v, guint * res)
|
||||
{
|
||||
const GstCapsFeatures *features = gst_value_get_caps_features (v);
|
||||
return gst_hash_caps_features (features, res);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_caps (const GValue * v, guint * res)
|
||||
{
|
||||
const GstCaps *caps = gst_value_get_caps (v);
|
||||
guint i;
|
||||
guint n = gst_caps_get_size (caps);
|
||||
|
||||
*res = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
GstCapsFeatures *features = gst_caps_get_features (caps, i);
|
||||
guint hash;
|
||||
|
||||
if (!gst_hash_structure (gst_caps_get_structure (caps, i), &hash))
|
||||
return FALSE;
|
||||
*res ^= hash;
|
||||
|
||||
if (!gst_hash_caps_features (features, &hash))
|
||||
return FALSE;
|
||||
*res ^= hash;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_tag_list (const GValue * v, guint * res)
|
||||
{
|
||||
const GstTagList *tags = g_value_get_boxed (v);
|
||||
const GstStructure *s;
|
||||
|
||||
s = _gst_tag_list_structure (tags);
|
||||
return gst_hash_structure (s, res);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_date (const GValue * v, guint * res)
|
||||
{
|
||||
const GDate *date = g_value_get_boxed (v);
|
||||
guint32 julian, year, month, day;
|
||||
|
||||
julian = g_date_get_julian (date);
|
||||
if (julian) {
|
||||
*res = g_int_hash ((gconstpointer) & julian);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
year = g_date_get_year (date);
|
||||
month = g_date_get_month (date);
|
||||
day = g_date_get_day (date);
|
||||
|
||||
*res = g_int_hash ((gconstpointer) & year);
|
||||
combine_hash_ordered (res, g_int_hash ((gconstpointer) & month));
|
||||
combine_hash_ordered (res, g_int_hash ((gconstpointer) & day));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_hash_g_date_time (const GDateTime * dt, guint * res)
|
||||
{
|
||||
gint64 unix_time;
|
||||
|
||||
unix_time = g_date_time_to_unix ((GDateTime *) dt);
|
||||
*res = g_int64_hash ((gconstpointer) & unix_time);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_g_date_time (const GValue * v, guint * res)
|
||||
{
|
||||
GDateTime *dt = g_value_get_boxed (v);
|
||||
return gst_hash_g_date_time (dt, res);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_date_time (const GValue * v, guint * res)
|
||||
{
|
||||
GstDateTime *dt = g_value_get_boxed (v);
|
||||
GDateTime *gdt;
|
||||
gboolean ret_val;
|
||||
|
||||
gdt = gst_date_time_to_g_date_time (dt);
|
||||
ret_val = gst_hash_g_date_time (gdt, res);
|
||||
|
||||
g_date_time_unref (gdt);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_bytes (const GValue * v, guint * res)
|
||||
{
|
||||
GBytes *bytes = g_value_get_boxed (v);
|
||||
const guint *data;
|
||||
gsize size, i;
|
||||
|
||||
*res = 0;
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
combine_hash_ordered (res, data[i]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_bitmask (const GValue * v, guint * res)
|
||||
{
|
||||
guint64 mask = gst_value_get_bitmask (v);
|
||||
*res = g_int64_hash ((gconstpointer) & mask);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_flagset (const GValue * v, guint * res)
|
||||
{
|
||||
guint flags = gst_value_get_flagset_flags (v);
|
||||
guint mask = gst_value_get_flagset_mask (v);
|
||||
guint value = flags & mask;
|
||||
*res = g_int_hash ((gconstpointer) & value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_segment (const GValue * v, guint * res)
|
||||
{
|
||||
GstSegment *segment = g_value_get_boxed (v);
|
||||
|
||||
*res = g_int_hash ((gconstpointer) & segment->flags);
|
||||
combine_hash_ordered (res, g_double_hash ((gconstpointer) & segment->rate));
|
||||
combine_hash_ordered (res,
|
||||
g_double_hash ((gconstpointer) & segment->applied_rate));
|
||||
combine_hash_ordered (res, g_int_hash ((gconstpointer) & segment->format));
|
||||
combine_hash_ordered (res, g_int64_hash ((gconstpointer) & segment->base));
|
||||
combine_hash_ordered (res, g_int64_hash ((gconstpointer) & segment->offset));
|
||||
combine_hash_ordered (res, g_int64_hash ((gconstpointer) & segment->start));
|
||||
combine_hash_ordered (res, g_int64_hash ((gconstpointer) & segment->stop));
|
||||
combine_hash_ordered (res, g_int64_hash ((gconstpointer) & segment->time));
|
||||
combine_hash_ordered (res,
|
||||
g_int64_hash ((gconstpointer) & segment->position));
|
||||
combine_hash_ordered (res,
|
||||
g_int64_hash ((gconstpointer) & segment->duration));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_allocation_params (const GValue * v, guint * res)
|
||||
{
|
||||
GstAllocationParams *params = g_value_get_boxed (v);
|
||||
|
||||
*res = g_int_hash ((gconstpointer) & params->flags);
|
||||
combine_hash_ordered (res, g_int64_hash ((gconstpointer) & params->align));
|
||||
combine_hash_ordered (res, g_int64_hash ((gconstpointer) & params->prefix));
|
||||
combine_hash_ordered (res, g_int64_hash ((gconstpointer) & params->padding));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_object (const GValue * v, guint * res)
|
||||
{
|
||||
GObject *obj = g_value_get_object (v);
|
||||
*res = g_direct_hash (obj);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_value_list (const GValue * v, guint * res)
|
||||
{
|
||||
guint i, n;
|
||||
|
||||
*res = 0;
|
||||
/* value list not ordered */
|
||||
n = gst_value_list_get_size (v);
|
||||
for (i = 0; i < n; i++) {
|
||||
guint value_hash;
|
||||
|
||||
if (!gst_value_hash (gst_value_list_get_value (v, i), &value_hash))
|
||||
return FALSE;
|
||||
*res ^= value_hash;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_value_array (const GValue * v, guint * res)
|
||||
{
|
||||
guint i, n;
|
||||
|
||||
*res = 0;
|
||||
/* value array is ordered */
|
||||
n = gst_value_array_get_size (v);
|
||||
for (i = 0; i < n; i++) {
|
||||
guint value_hash;
|
||||
|
||||
if (!gst_value_hash (gst_value_array_get_value (v, i), &value_hash))
|
||||
return FALSE;
|
||||
combine_hash_ordered (res, value_hash);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_hash_strv (const GValue * v, guint * res)
|
||||
{
|
||||
GStrv strv = g_value_get_boxed (v);
|
||||
guint i, n;
|
||||
|
||||
*res = 0;
|
||||
|
||||
/* GStrv is ordered */
|
||||
n = g_strv_length (strv);
|
||||
for (i = 0; i < n; i++) {
|
||||
combine_hash_ordered (res, g_str_hash (strv[i]));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************
|
||||
* GstAllocationParams *
|
||||
***********************/
|
||||
@ -8411,14 +8956,15 @@ gst_g_thread_get_type (void)
|
||||
return G_TYPE_THREAD;
|
||||
}
|
||||
|
||||
#define SERIAL_VTABLE(t,c,s,d) { t, c, s, d, NULL }
|
||||
#define SERIAL_VTABLE_PSPEC(t,c,s,d) { t, c, s, NULL, d }
|
||||
#define SERIAL_VTABLE(t,c,s,d,h) { t, c, s, d, NULL, h }
|
||||
#define SERIAL_VTABLE_PSPEC(t,c,s,d,h) { t, c, s, NULL, d, h }
|
||||
|
||||
#define REGISTER_SERIALIZATION_CONST(_gtype, _type) \
|
||||
G_STMT_START { \
|
||||
static const GstValueTable gst_value = \
|
||||
SERIAL_VTABLE (_gtype, gst_value_compare_ ## _type, \
|
||||
gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
|
||||
gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type, \
|
||||
gst_value_hash_ ## _type); \
|
||||
gst_value_register (&gst_value); \
|
||||
} G_STMT_END
|
||||
|
||||
@ -8426,7 +8972,8 @@ G_STMT_START { \
|
||||
G_STMT_START { \
|
||||
static GstValueTable gst_value = \
|
||||
SERIAL_VTABLE (0, gst_value_compare_ ## _type, \
|
||||
gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
|
||||
gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type, \
|
||||
gst_value_hash_ ## _type); \
|
||||
gst_value.type = _gtype; \
|
||||
gst_value_register (&gst_value); \
|
||||
} G_STMT_END
|
||||
@ -8435,7 +8982,8 @@ G_STMT_START { \
|
||||
G_STMT_START { \
|
||||
static GstValueTable gst_value = \
|
||||
SERIAL_VTABLE_PSPEC (0, gst_value_compare_ ## _type, \
|
||||
gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
|
||||
gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type, \
|
||||
gst_value_hash_ ## _type); \
|
||||
gst_value.type = _gtype; \
|
||||
gst_value_register (&gst_value); \
|
||||
} G_STMT_END
|
||||
@ -8444,7 +8992,8 @@ G_STMT_START { \
|
||||
G_STMT_START { \
|
||||
static GstValueTable gst_value = \
|
||||
SERIAL_VTABLE (0, NULL, \
|
||||
gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
|
||||
gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type, \
|
||||
gst_value_hash_ ## _type); \
|
||||
gst_value.type = _gtype; \
|
||||
gst_value_register (&gst_value); \
|
||||
} G_STMT_END
|
||||
@ -8453,7 +9002,7 @@ G_STMT_START { \
|
||||
G_STMT_START { \
|
||||
static GstValueTable gst_value = \
|
||||
SERIAL_VTABLE (0, gst_value_compare_ ## _type, \
|
||||
NULL, NULL); \
|
||||
NULL, NULL, gst_value_hash_ ## _type); \
|
||||
gst_value.type = _gtype; \
|
||||
gst_value_register (&gst_value); \
|
||||
} G_STMT_END
|
||||
@ -8703,3 +9252,58 @@ gst_flagset_register (GType flags_type)
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_value_hash:
|
||||
* @value: a #GValue to hash
|
||||
* @res: (out): a location to store the hash value
|
||||
*
|
||||
* Compute a hash value of @value.
|
||||
* #GValue considered as equals by gst_value_compare() will have the same hash value.
|
||||
*
|
||||
* Returns: %TRUE, or %FALSE if @value cannot be hashed.
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
gboolean
|
||||
gst_value_hash (const GValue * value, guint * res)
|
||||
{
|
||||
GType type;
|
||||
GstValueTable *table;
|
||||
|
||||
g_return_val_if_fail (res, FALSE);
|
||||
*res = 0;
|
||||
|
||||
type = G_VALUE_TYPE (value);
|
||||
|
||||
table = gst_value_hash_lookup_type (type);
|
||||
|
||||
if (G_LIKELY (table && table->hash)) {
|
||||
if (type == GST_TYPE_LIST && gst_value_list_get_size (value) == 1) {
|
||||
/* { 1 } and 1 are considered as equals so hash the single element contained in the list */
|
||||
const GValue *v = gst_value_list_get_value (value, 0);
|
||||
return gst_value_hash (v, res);
|
||||
} else if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_INT64_RANGE) {
|
||||
/* hash the list type as list and ranges of the same values are considered as equals */
|
||||
type = GST_TYPE_LIST;
|
||||
}
|
||||
guint hash;
|
||||
|
||||
*res = g_int_hash ((gconstpointer) & type);
|
||||
if (!table->hash (value, &hash))
|
||||
return FALSE;
|
||||
*res ^= hash;
|
||||
return TRUE;
|
||||
} else {
|
||||
/* custom enums and flags are not registered through gst_value_register() and so don't have a table entry */
|
||||
if G_VALUE_HOLDS_ENUM
|
||||
(value) {
|
||||
return gst_value_hash_enum (value, res);
|
||||
} else if G_VALUE_HOLDS_FLAGS
|
||||
(value) {
|
||||
return gst_value_hash_gflags (value, res);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -487,6 +487,19 @@ typedef gboolean (* GstValueDeserializeWithPSpecFunc) (GValue *dest,
|
||||
const gchar *s,
|
||||
GParamSpec *pspec);
|
||||
|
||||
/**
|
||||
* GstValueHashFunc:
|
||||
* @value: a #GValue
|
||||
* @res: (out): a location to store the hash value
|
||||
*
|
||||
* Used by gst_value_hash() to calculate a hash of @value.
|
||||
*
|
||||
* Returns: %TRUE, or %FALSE if @value cannot be hashed.
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
typedef gboolean (* GstValueHashFunc) (const GValue *value,
|
||||
guint *res);
|
||||
|
||||
typedef struct _GstValueTable GstValueTable;
|
||||
/**
|
||||
@ -514,8 +527,17 @@ struct _GstValueTable {
|
||||
*/
|
||||
GstValueDeserializeWithPSpecFunc deserialize_with_pspec;
|
||||
|
||||
/**
|
||||
* GstValueTable.hash:
|
||||
*
|
||||
* a #GstValueHashFunc
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
GstValueHashFunc hash;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved [GST_PADDING - 1];
|
||||
gpointer _gst_reserved [GST_PADDING - 2];
|
||||
};
|
||||
|
||||
GST_API
|
||||
@ -569,6 +591,10 @@ gboolean gst_value_deserialize_with_pspec (GValue *dest,
|
||||
const gchar *src,
|
||||
GParamSpec *pspec);
|
||||
|
||||
GST_API
|
||||
gboolean gst_value_hash (const GValue * value,
|
||||
guint * res);
|
||||
|
||||
/* list */
|
||||
|
||||
GST_API
|
||||
|
@ -4063,6 +4063,435 @@ GST_START_TEST (test_serialize_deserialize_strv)
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
/* take ownership of @a and @b */
|
||||
static void
|
||||
test_hash_value_diff (GValue * a, GValue * b, gboolean compare)
|
||||
{
|
||||
guint hash_a, hash_b;
|
||||
|
||||
if (compare) {
|
||||
fail_unless (gst_value_compare (a, a) == GST_VALUE_EQUAL,
|
||||
"[%s] value should be equal: \"%s\" \"%s\"",
|
||||
G_VALUE_TYPE_NAME (a), gst_value_serialize (a),
|
||||
gst_value_serialize (a));
|
||||
fail_unless (gst_value_compare (b, b) == GST_VALUE_EQUAL,
|
||||
"[%s] value should be equal: \"%s\" \"%s\"", G_VALUE_TYPE_NAME (a),
|
||||
gst_value_serialize (b), gst_value_serialize (b));
|
||||
fail_unless (gst_value_compare (a, b) != GST_VALUE_EQUAL,
|
||||
"[%s] value should be different: \"%s\" \"%s\"", G_VALUE_TYPE_NAME (a),
|
||||
gst_value_serialize (a), gst_value_serialize (b));
|
||||
}
|
||||
|
||||
fail_unless (gst_value_hash (a, &hash_a),
|
||||
"[%s] failed to hash: \"%s\"",
|
||||
G_VALUE_TYPE_NAME (a), gst_value_serialize (a));
|
||||
fail_unless (gst_value_hash (b, &hash_b),
|
||||
"[%s] failed to hash: \"%s\"",
|
||||
G_VALUE_TYPE_NAME (b), gst_value_serialize (b));
|
||||
fail_unless (hash_a != hash_b,
|
||||
"[%s] hash should be different: \"%s\" \"%s\"",
|
||||
G_VALUE_TYPE_NAME (a), gst_value_serialize (a), gst_value_serialize (b));
|
||||
|
||||
g_value_unset (a);
|
||||
g_value_unset (b);
|
||||
}
|
||||
|
||||
/* take ownership of @a and @b */
|
||||
static void
|
||||
test_hash_value_equal (GValue * a, GValue * b, gboolean compare)
|
||||
{
|
||||
guint hash_a, hash_b;
|
||||
|
||||
if (compare) {
|
||||
fail_unless (gst_value_compare (a, a) == GST_VALUE_EQUAL,
|
||||
"[%s] value should be equal: \"%s\" \"%s\"",
|
||||
G_VALUE_TYPE_NAME (a), gst_value_serialize (a),
|
||||
gst_value_serialize (a));
|
||||
fail_unless (gst_value_compare (b, b) == GST_VALUE_EQUAL,
|
||||
"[%s] value should be equal: \"%s\" \"%s\"", G_VALUE_TYPE_NAME (a),
|
||||
gst_value_serialize (b), gst_value_serialize (b));
|
||||
fail_unless (gst_value_compare (a, b) == GST_VALUE_EQUAL,
|
||||
"[%s] value should be equal: \"%s\" \"%s\"", G_VALUE_TYPE_NAME (a),
|
||||
gst_value_serialize (a), gst_value_serialize (b));
|
||||
}
|
||||
|
||||
fail_unless (gst_value_hash (a, &hash_a),
|
||||
"[%s] failed to hash: \"%s\"",
|
||||
G_VALUE_TYPE_NAME (a), gst_value_serialize (a));
|
||||
fail_unless (gst_value_hash (b, &hash_b),
|
||||
"[%s] failed to hash: \"%s\"",
|
||||
G_VALUE_TYPE_NAME (b), gst_value_serialize (b));
|
||||
fail_unless (hash_a == hash_b,
|
||||
"[%s] hash should be equal: \"%s\" \"%s\"",
|
||||
G_VALUE_TYPE_NAME (a), gst_value_serialize (a), gst_value_serialize (b));
|
||||
|
||||
g_value_unset (a);
|
||||
g_value_unset (b);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_hash)
|
||||
{
|
||||
guint i;
|
||||
/* tests where we can rely on gst_value_deserialize() to set GValue */
|
||||
struct HashTest
|
||||
{
|
||||
GType gtype;
|
||||
const gchar *a;
|
||||
const gchar *b;
|
||||
gboolean compare;
|
||||
};
|
||||
|
||||
/* check that a and b are different */
|
||||
struct HashTest tests_diff[] = {
|
||||
{G_TYPE_INT, "1", "2", TRUE},
|
||||
{G_TYPE_INT64, "1", "2", TRUE},
|
||||
{G_TYPE_LONG, "1", "2", TRUE},
|
||||
{G_TYPE_UINT, "1", "2", TRUE},
|
||||
{G_TYPE_UINT64, "1", "2", TRUE},
|
||||
{G_TYPE_ULONG, "1", "2", TRUE},
|
||||
{G_TYPE_UCHAR, "1", "2", TRUE},
|
||||
{G_TYPE_GTYPE, "gint", "gint64", TRUE},
|
||||
{G_TYPE_DOUBLE, "1.0", "2.0", TRUE},
|
||||
{G_TYPE_FLOAT, "1.0", "2.0", TRUE},
|
||||
{G_TYPE_STRING, "a", "b", TRUE},
|
||||
{G_TYPE_BOOLEAN, "TRUE", "FALSE", TRUE},
|
||||
{GST_TYPE_BUFFER, "ab", "abcd", TRUE},
|
||||
/* only difference is the buffer content */
|
||||
{GST_TYPE_SAMPLE,
|
||||
"6275660a64617400:Y2FwcywgSW50PShpbnQpMjAsIFN0cmluZz0oc3RyaW5nKSJhXCBzdHJpbmciAA__:c2VnbWVudCwgZmxhZ3M9KEdzdFNlZ21lbnRGbGFncylHU1RfU0VHTUVOVF9GTEFHX1JFU0VULCByYXRlPShkb3VibGUpMS4yLCBhcHBsaWVkLXJhdGU9KGRvdWJsZSkxLCBmb3JtYXQ9KEdzdEZvcm1hdClkZWZhdWx0LCBiYXNlPShndWludDY0KTAsIG9mZnNldD0oZ3VpbnQ2NCkwLCBzdGFydD0oZ3VpbnQ2NCkyMCwgc3RvcD0oZ3VpbnQ2NCkzMCwgdGltZT0oZ3VpbnQ2NCkyMCwgcG9zaXRpb249KGd1aW50NjQpMjAsIGR1cmF0aW9uPShndWludDY0KTE4NDQ2NzQ0MDczNzA5NTUxNjE1OwA_:c3RydWN0dXJlLCBGbG9hdD0oZmxvYXQpLTIuNTsA",
|
||||
"4255460a44415400:Y2FwcywgSW50PShpbnQpMjAsIFN0cmluZz0oc3RyaW5nKSJhXCBzdHJpbmciAA__:c2VnbWVudCwgZmxhZ3M9KEdzdFNlZ21lbnRGbGFncylHU1RfU0VHTUVOVF9GTEFHX1JFU0VULCByYXRlPShkb3VibGUpMS4yLCBhcHBsaWVkLXJhdGU9KGRvdWJsZSkxLCBmb3JtYXQ9KEdzdEZvcm1hdClkZWZhdWx0LCBiYXNlPShndWludDY0KTAsIG9mZnNldD0oZ3VpbnQ2NCkwLCBzdGFydD0oZ3VpbnQ2NCkyMCwgc3RvcD0oZ3VpbnQ2NCkzMCwgdGltZT0oZ3VpbnQ2NCkyMCwgcG9zaXRpb249KGd1aW50NjQpMjAsIGR1cmF0aW9uPShndWludDY0KTE4NDQ2NzQ0MDczNzA5NTUxNjE1OwA_:c3RydWN0dXJlLCBGbG9hdD0oZmxvYXQpLTIuNTsA",
|
||||
TRUE},
|
||||
{GST_TYPE_FRACTION, "1/3", "3/1", TRUE},
|
||||
{GST_TYPE_STRUCTURE, "video/x-raw", "audio/x-raw", TRUE},
|
||||
{GST_TYPE_STRUCTURE, "video/x-raw,width=1920", "video/x-raw,width=800",
|
||||
TRUE},
|
||||
{GST_TYPE_CAPS, "video/x-raw", "audio/x-raw", TRUE},
|
||||
{GST_TYPE_CAPS, "video/x-raw,width=1920", "video/x-raw,width=800", TRUE},
|
||||
{GST_TYPE_CAPS, "video/x-raw", "video/x-raw(memory:DMABuf)", TRUE},
|
||||
{GST_TYPE_TAG_LIST, "taglist, title=(string)Title, artist=(string)Artist",
|
||||
"taglist, title=(string)Title2, artist=(string)Artist", TRUE},
|
||||
{G_TYPE_DATE, "1984-11-30", "1985-11-30", TRUE},
|
||||
{G_TYPE_DATE_TIME, "2011-06-23T07:40:10Z", "2011-06-23T07:40:11Z", TRUE},
|
||||
{GST_TYPE_DATE_TIME, "2011-06-23T07:40:10Z", "2011-06-23T07:40:11Z",
|
||||
TRUE},
|
||||
{G_TYPE_BYTES, "YQ==", "Yg==", TRUE},
|
||||
{GST_TYPE_BITMASK, "0xaa", "0xbb", TRUE},
|
||||
{GST_TYPE_SEEK_FLAGS, "+flush", "+flush+trickmode/trickmode-no-audio",
|
||||
TRUE},
|
||||
{GST_TYPE_LIST, "{1, 2}", "{1, 3}", TRUE},
|
||||
{GST_TYPE_CAPS_FEATURES, "memory:DMABuf", "memory:GLMemory", FALSE},
|
||||
};
|
||||
|
||||
/* check that a and b are equal */
|
||||
struct HashTest tests_equal[] = {
|
||||
/* structures fields are not ordered */
|
||||
{GST_TYPE_STRUCTURE, "video/x-raw,width=1920,height=1080",
|
||||
"video/x-raw,height=1080,width=1920", TRUE},
|
||||
/* fixed and unfixed caps are not ordered */
|
||||
{GST_TYPE_CAPS, "video/x-raw; audio/x-raw", "audio/x-raw; video/x-raw",
|
||||
TRUE},
|
||||
{GST_TYPE_CAPS,
|
||||
"video/x-raw,format=NV12,width=[1, 100]; video/x-raw,format=GREY8,width=[1, 100]",
|
||||
"video/x-raw,format=GREY8,width=[1, 100]; video/x-raw,format=NV12,width=[1, 100]",
|
||||
TRUE},
|
||||
{GST_TYPE_LIST, "{1, 2}", "{2, 1}", TRUE},
|
||||
{GST_TYPE_LIST, "{1, 2}", "{2, 1}", TRUE},
|
||||
/* caps features are not ordered */
|
||||
{GST_TYPE_CAPS_FEATURES, "memory:DMABuf, memory:GLMemory",
|
||||
"memory:GLMemory, memory:DMABuf", FALSE},
|
||||
/* same actual fraction have the same hash */
|
||||
{GST_TYPE_FRACTION, "1/2", "2/4", TRUE},
|
||||
};
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (tests_diff); i++) {
|
||||
GValue a = G_VALUE_INIT;
|
||||
GValue b = G_VALUE_INIT;
|
||||
|
||||
g_value_init (&a, tests_diff[i].gtype);
|
||||
fail_unless (gst_value_deserialize (&a, tests_diff[i].a),
|
||||
"[%s] could not deserialize %s", g_type_name (tests_diff[i].gtype),
|
||||
tests_diff[i].a);
|
||||
g_value_init (&b, tests_diff[i].gtype);
|
||||
fail_unless (gst_value_deserialize (&b, tests_diff[i].b),
|
||||
"[%s] could not deserialize %s", g_type_name (tests_diff[i].gtype),
|
||||
tests_diff[i].b);
|
||||
|
||||
test_hash_value_diff (&a, &b, tests_diff[i].compare);
|
||||
}
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (tests_equal); i++) {
|
||||
GValue a = G_VALUE_INIT;
|
||||
GValue b = G_VALUE_INIT;
|
||||
|
||||
g_value_init (&a, tests_equal[i].gtype);
|
||||
fail_unless (gst_value_deserialize (&a, tests_equal[i].a),
|
||||
"[%s] could not deserialize %s", g_type_name (tests_equal[i].gtype),
|
||||
tests_equal[i].a);
|
||||
g_value_init (&b, tests_equal[i].gtype);
|
||||
fail_unless (gst_value_deserialize (&b, tests_equal[i].b),
|
||||
"[%s] could not deserialize %s", g_type_name (tests_equal[i].gtype),
|
||||
tests_equal[i].b);
|
||||
|
||||
test_hash_value_equal (&a, &b, tests_equal[i].compare);
|
||||
}
|
||||
|
||||
/* tests for types not implementing deserialize */
|
||||
{
|
||||
GValue a = G_VALUE_INIT;
|
||||
GValue b = G_VALUE_INIT;
|
||||
GValue v = G_VALUE_INIT;
|
||||
GValueArray *array;
|
||||
|
||||
/* int range */
|
||||
g_value_init (&a, GST_TYPE_INT_RANGE);
|
||||
g_value_init (&b, GST_TYPE_INT_RANGE);
|
||||
gst_value_set_int_range (&a, 0, 2);
|
||||
gst_value_set_int_range (&b, 0, 3);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* int range with step */
|
||||
g_value_init (&a, GST_TYPE_INT_RANGE);
|
||||
g_value_init (&b, GST_TYPE_INT_RANGE);
|
||||
gst_value_set_int_range_step (&a, 0, 12, 2);
|
||||
gst_value_set_int_range_step (&b, 0, 12, 4);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* int64 range */
|
||||
g_value_init (&a, GST_TYPE_INT64_RANGE);
|
||||
g_value_init (&b, GST_TYPE_INT64_RANGE);
|
||||
gst_value_set_int64_range (&a, 0, 2);
|
||||
gst_value_set_int64_range (&b, 0, 3);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* int64 range with step */
|
||||
g_value_init (&a, GST_TYPE_INT64_RANGE);
|
||||
g_value_init (&b, GST_TYPE_INT64_RANGE);
|
||||
gst_value_set_int64_range_step (&a, 0, 12, 2);
|
||||
gst_value_set_int64_range_step (&b, 0, 12, 4);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* double range */
|
||||
g_value_init (&a, GST_TYPE_DOUBLE_RANGE);
|
||||
g_value_init (&b, GST_TYPE_DOUBLE_RANGE);
|
||||
gst_value_set_double_range (&a, 0, 12);
|
||||
gst_value_set_double_range (&b, 0, 13);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* enum */
|
||||
static const GEnumValue test_enum_vals[] = {
|
||||
{0, "Badger", "badger"},
|
||||
{1, "Mushroom", "mushroom"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
GType test_enum_type =
|
||||
g_enum_register_static ("GstTestEnum", test_enum_vals);
|
||||
g_value_init (&a, test_enum_type);
|
||||
g_value_set_enum (&a, 0);
|
||||
g_value_init (&b, test_enum_type);
|
||||
g_value_set_enum (&b, 1);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* flags */
|
||||
static const GFlagsValue test_flags_vals[] = {
|
||||
{0, "Badger", "badger"},
|
||||
{1, "Mushroom", "mushroom"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
GType test_flags_type =
|
||||
g_flags_register_static ("GstTestFlags", test_flags_vals);
|
||||
g_value_init (&a, test_flags_type);
|
||||
g_value_set_flags (&a, 0);
|
||||
g_value_init (&b, test_flags_type);
|
||||
g_value_set_flags (&b, 1);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* value array */
|
||||
setup_test_value_array (&a);
|
||||
setup_test_value_array (&b);
|
||||
GValueArray *arr = g_value_get_boxed (&b);
|
||||
g_value_init (&v, G_TYPE_INT);
|
||||
g_value_set_int (&v, 4);
|
||||
g_value_array_append (arr, &v);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
g_value_unset (&v);
|
||||
|
||||
g_value_init (&v, G_TYPE_INT);
|
||||
g_value_init (&a, G_TYPE_VALUE_ARRAY);
|
||||
array = g_value_array_new (2);
|
||||
g_value_set_int (&v, 1);
|
||||
g_value_array_append (array, &v);
|
||||
g_value_set_int (&v, 2);
|
||||
g_value_array_append (array, &v);
|
||||
g_value_take_boxed (&a, array);
|
||||
array = g_value_array_new (2);
|
||||
g_value_init (&b, G_TYPE_VALUE_ARRAY);
|
||||
g_value_set_int (&v, 2);
|
||||
g_value_array_append (array, &v);
|
||||
g_value_set_int (&v, 1);
|
||||
g_value_array_append (array, &v);
|
||||
g_value_take_boxed (&b, array);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
g_value_unset (&v);
|
||||
|
||||
/* fraction range */
|
||||
g_value_init (&a, GST_TYPE_FRACTION_RANGE);
|
||||
g_value_init (&b, GST_TYPE_FRACTION_RANGE);
|
||||
gst_value_set_fraction_range_full (&a, 1, 5, 4, 5);
|
||||
gst_value_set_fraction_range_full (&a, 2, 5, 4, 5);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* objet */
|
||||
GstBufferPool *obj_a = gst_buffer_pool_new ();
|
||||
GstBufferPool *obj_b = gst_buffer_pool_new ();
|
||||
g_value_init (&a, G_TYPE_OBJECT);
|
||||
g_value_take_object (&a, obj_a);
|
||||
g_value_init (&b, G_TYPE_OBJECT);
|
||||
g_value_take_object (&b, obj_b);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* value array */
|
||||
g_value_init (&a, GST_TYPE_ARRAY);
|
||||
g_value_init (&v, G_TYPE_INT);
|
||||
g_value_set_int (&v, 1);
|
||||
gst_value_array_append_value (&a, &v);
|
||||
g_value_set_int (&v, 2);
|
||||
gst_value_array_append_value (&a, &v);
|
||||
g_value_init (&b, GST_TYPE_ARRAY);
|
||||
g_value_set_int (&v, 2);
|
||||
gst_value_array_append_value (&b, &v);
|
||||
g_value_set_int (&v, 2);
|
||||
gst_value_array_append_value (&b, &v);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
g_value_unset (&v);
|
||||
|
||||
/* AllocationParams */
|
||||
GstAllocationParams params_a = { 0 }, params_b;
|
||||
params_a.flags = 0;
|
||||
params_a.align = 1;
|
||||
params_a.prefix = 2;
|
||||
params_a.padding = 3;
|
||||
params_b = params_a;
|
||||
params_b.padding = 4;
|
||||
g_value_init (&a, GST_TYPE_ALLOCATION_PARAMS);
|
||||
g_value_set_boxed (&a, ¶ms_a);
|
||||
g_value_init (&b, GST_TYPE_ALLOCATION_PARAMS);
|
||||
g_value_set_boxed (&b, ¶ms_b);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* float NaN */
|
||||
g_value_init (&a, G_TYPE_FLOAT);
|
||||
g_value_set_float (&a, NAN);
|
||||
g_value_init (&b, G_TYPE_FLOAT);
|
||||
g_value_set_float (&b, 0);
|
||||
test_hash_value_diff (&a, &b, FALSE);
|
||||
}
|
||||
|
||||
/* types with specific compare function */
|
||||
{
|
||||
GValue a = G_VALUE_INIT;
|
||||
GValue b = G_VALUE_INIT;
|
||||
|
||||
GstSegment seg_a, seg_b;
|
||||
gst_segment_init (&seg_a, GST_FORMAT_DEFAULT);
|
||||
fail_unless (gst_segment_do_seek (&seg_a, 1.2, GST_FORMAT_DEFAULT,
|
||||
GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 20, GST_SEEK_TYPE_SET, 30,
|
||||
NULL));
|
||||
seg_b = seg_a;
|
||||
seg_b.rate = 1.0;
|
||||
fail_unless (!gst_segment_is_equal (&seg_a, &seg_b));
|
||||
g_value_init (&a, GST_TYPE_SEGMENT);
|
||||
g_value_set_boxed (&a, &seg_a);
|
||||
g_value_init (&b, GST_TYPE_SEGMENT);
|
||||
g_value_set_boxed (&b, &seg_b);
|
||||
test_hash_value_diff (&a, &b, FALSE);
|
||||
|
||||
g_value_init (&a, G_TYPE_STRV);
|
||||
fail_unless (gst_value_deserialize (&a, "<\"foo\",\"bar\">"));
|
||||
g_value_init (&b, G_TYPE_STRV);
|
||||
fail_unless (gst_value_deserialize (&b, "<\"bar\",\"foo\">"));
|
||||
fail_unless (!g_strv_equal (g_value_get_boxed (&a),
|
||||
g_value_get_boxed (&b)));
|
||||
test_hash_value_diff (&a, &b, FALSE);
|
||||
}
|
||||
|
||||
// gst_value_compare() special cases
|
||||
{
|
||||
GValue a = G_VALUE_INIT;
|
||||
GValue b = G_VALUE_INIT;
|
||||
GValue v = G_VALUE_INIT;
|
||||
|
||||
/* { 1 } and 1 are considered as equals */
|
||||
g_value_init (&a, GST_TYPE_LIST);
|
||||
fail_unless (gst_value_deserialize (&a, "{ 1 }"));
|
||||
g_value_init (&b, G_TYPE_INT);
|
||||
fail_unless (gst_value_deserialize (&b, "1"));
|
||||
test_hash_value_equal (&a, &b, TRUE);
|
||||
|
||||
/* list and range are considered as equal if they contain the same set of elements */
|
||||
g_value_init (&a, GST_TYPE_LIST);
|
||||
fail_unless (gst_value_deserialize (&a, "{ 1, 2 }"));
|
||||
g_value_init (&b, GST_TYPE_INT_RANGE);
|
||||
gst_value_set_int_range (&b, 1, 2);
|
||||
test_hash_value_equal (&a, &b, TRUE);
|
||||
|
||||
/* same set with steps */
|
||||
g_value_init (&a, GST_TYPE_LIST);
|
||||
fail_unless (gst_value_deserialize (&a, "{ 2, 4, 6, 8 }"));
|
||||
g_value_init (&b, GST_TYPE_INT_RANGE);
|
||||
gst_value_set_int_range_step (&b, 2, 8, 2);
|
||||
test_hash_value_equal (&a, &b, TRUE);
|
||||
|
||||
/* different step */
|
||||
g_value_init (&a, GST_TYPE_LIST);
|
||||
fail_unless (gst_value_deserialize (&a, "{ 1, 3 }"));
|
||||
g_value_init (&b, GST_TYPE_INT_RANGE);
|
||||
gst_value_set_int_range (&b, 1, 3);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
|
||||
/* same for int64 range */
|
||||
g_value_init (&a, GST_TYPE_LIST);
|
||||
g_value_init (&v, G_TYPE_INT64);
|
||||
g_value_set_int64 (&v, 1);
|
||||
gst_value_list_append_and_take_value (&a, &v);
|
||||
g_value_init (&v, G_TYPE_INT64);
|
||||
g_value_set_int64 (&v, 2);
|
||||
gst_value_list_append_and_take_value (&a, &v);
|
||||
g_value_init (&b, GST_TYPE_INT64_RANGE);
|
||||
gst_value_set_int64_range (&b, 1, 2);
|
||||
test_hash_value_equal (&a, &b, TRUE);
|
||||
|
||||
g_value_init (&a, GST_TYPE_LIST);
|
||||
g_value_init (&v, G_TYPE_INT64);
|
||||
g_value_set_int64 (&v, 2);
|
||||
gst_value_list_append_and_take_value (&a, &v);
|
||||
g_value_init (&v, G_TYPE_INT64);
|
||||
g_value_set_int64 (&v, 4);
|
||||
gst_value_list_append_and_take_value (&a, &v);
|
||||
g_value_init (&v, G_TYPE_INT64);
|
||||
g_value_set_int64 (&v, 6);
|
||||
gst_value_list_append_and_take_value (&a, &v);
|
||||
g_value_init (&v, G_TYPE_INT64);
|
||||
g_value_set_int64 (&v, 8);
|
||||
gst_value_list_append_and_take_value (&a, &v);
|
||||
g_value_init (&b, GST_TYPE_INT64_RANGE);
|
||||
gst_value_set_int64_range_step (&b, 2, 8, 2);
|
||||
test_hash_value_equal (&a, &b, TRUE);
|
||||
|
||||
g_value_init (&a, GST_TYPE_LIST);
|
||||
g_value_init (&v, G_TYPE_INT64);
|
||||
g_value_set_int64 (&v, 1);
|
||||
gst_value_list_append_and_take_value (&a, &v);
|
||||
g_value_init (&v, G_TYPE_INT64);
|
||||
g_value_set_int64 (&v, 3);
|
||||
gst_value_list_append_and_take_value (&a, &v);
|
||||
g_value_init (&b, GST_TYPE_INT64_RANGE);
|
||||
gst_value_set_int64_range (&b, 1, 3);
|
||||
test_hash_value_diff (&a, &b, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
gst_value_suite (void)
|
||||
{
|
||||
@ -4126,6 +4555,7 @@ gst_value_suite (void)
|
||||
tcase_add_test (tc_chain, test_serialize_deserialize_tag_list);
|
||||
tcase_add_test (tc_chain, test_serialize_deserialize_sample);
|
||||
tcase_add_test (tc_chain, test_serialize_deserialize_strv);
|
||||
tcase_add_test (tc_chain, test_hash);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user