From c2175db8899f8bf1ad1ff4b886943966ed506f80 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 16 Sep 2012 23:20:46 +0100 Subject: [PATCH] sample: add serialisation/deserialisation functions for GstSample Since these things are inside taglists now, it would be good to be able to print them and deserialise them. https://bugzilla.gnome.org/show_bug.cgi?id=681322 --- gst/gststructure.c | 2 + gst/gstvalue.c | 164 +++++++++++++++++++++++++++++++++++++++++++++-- tests/check/gst/gsttag.c | 43 +++++++++++++ 3 files changed, 204 insertions(+), 5 deletions(-) diff --git a/gst/gststructure.c b/gst/gststructure.c index 56b66bc..29fdf31 100644 --- a/gst/gststructure.c +++ b/gst/gststructure.c @@ -1682,6 +1682,8 @@ gst_structure_get_abbrs (gint * n_abbrs) , {"bitmask", GST_TYPE_BITMASK} , + {"sample", GST_TYPE_SAMPLE} + , {"taglist", GST_TYPE_TAG_LIST} }; _num = G_N_ELEMENTS (dyn_abbrs); diff --git a/gst/gstvalue.c b/gst/gstvalue.c index 997a5e1..80c59fe 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -1837,8 +1837,9 @@ gst_value_deserialize_caps (GValue * dest, const gchar * s) /************** * GstSegment * **************/ + static gchar * -gst_value_serialize_segment (const GValue * value) +gst_value_serialize_segment_internal (const GValue * value, gboolean escape) { GstSegment *seg = g_value_get_boxed (value); gchar *t, *res; @@ -1857,13 +1858,23 @@ gst_value_serialize_segment (const GValue * value) "position", G_TYPE_UINT64, seg->position, "duration", G_TYPE_UINT64, seg->duration, NULL); t = gst_structure_to_string (s); - res = g_strdup_printf ("\"%s\"", t); - g_free (t); + if (escape) { + res = g_strdup_printf ("\"%s\"", t); + g_free (t); + } else { + res = t; + } gst_structure_free (s); return res; } +static gchar * +gst_value_serialize_segment (const GValue * value) +{ + return gst_value_serialize_segment_internal (value, TRUE); +} + static gboolean gst_value_deserialize_segment (GValue * dest, const gchar * s) { @@ -2151,6 +2162,149 @@ gst_value_compare_sample (const GValue * value1, const GValue * value2) return compare_buffer (buf1, buf2); } +static gchar * +gst_value_serialize_sample (const GValue * value) +{ + const GstStructure *info_structure; + GstSegment *segment; + GstBuffer *buffer; + GstCaps *caps; + GstSample *sample; + GValue val = { 0, }; + gchar *info_str, *caps_str, *tmp; + gchar *buf_str, *seg_str, *s; + + sample = g_value_get_boxed (value); + + buffer = gst_sample_get_buffer (sample); + if (buffer) { + g_value_init (&val, GST_TYPE_BUFFER); + g_value_set_boxed (&val, buffer); + buf_str = gst_value_serialize_buffer (&val); + g_value_unset (&val); + } else { + buf_str = g_strdup ("None"); + } + + caps = gst_sample_get_caps (sample); + if (caps) { + tmp = gst_caps_to_string (caps); + caps_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1); + g_strdelimit (caps_str, "=", '_'); + g_free (tmp); + } else { + caps_str = g_strdup ("None"); + } + + segment = gst_sample_get_segment (sample); + if (segment) { + g_value_init (&val, GST_TYPE_SEGMENT); + g_value_set_boxed (&val, segment); + tmp = gst_value_serialize_segment_internal (&val, FALSE); + seg_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1); + g_strdelimit (seg_str, "=", '_'); + g_free (tmp); + g_value_unset (&val); + } else { + seg_str = g_strdup ("None"); + } + + info_structure = gst_sample_get_info (sample); + if (info_structure) { + tmp = gst_structure_to_string (info_structure); + info_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1); + g_strdelimit (info_str, "=", '_'); + g_free (tmp); + } else { + info_str = g_strdup ("None"); + } + + s = g_strconcat (buf_str, ":", caps_str, ":", seg_str, ":", info_str, NULL); + g_free (buf_str); + g_free (caps_str); + g_free (seg_str); + g_free (info_str); + + return s; +} + +static gboolean +gst_value_deserialize_sample (GValue * dest, const gchar * s) +{ + GValue bval = G_VALUE_INIT, sval = G_VALUE_INIT; + GstStructure *info; + GstSample *sample; + GstCaps *caps; + gboolean ret = FALSE; + gchar **fields; + gsize outlen; + gint len; + + GST_TRACE ("deserialize '%s'", s); + + fields = g_strsplit (s, ":", -1); + len = g_strv_length (fields); + if (len != 4) + goto wrong_length; + + g_value_init (&bval, GST_TYPE_BUFFER); + g_value_init (&sval, GST_TYPE_SEGMENT); + + if (!gst_value_deserialize_buffer (&bval, fields[0])) + goto fail; + + if (strcmp (fields[1], "None") != 0) { + g_strdelimit (fields[1], "_", '='); + g_base64_decode_inplace (fields[1], &outlen); + GST_TRACE ("caps : %s", fields[1]); + caps = gst_caps_from_string (fields[1]); + if (caps == NULL) + goto fail; + } else { + caps = NULL; + } + + if (strcmp (fields[2], "None") != 0) { + g_strdelimit (fields[2], "_", '='); + g_base64_decode_inplace (fields[2], &outlen); + GST_TRACE ("segment : %s", fields[2]); + if (!gst_value_deserialize_segment (&sval, fields[2])) + goto fail; + } + + if (strcmp (fields[3], "None") != 0) { + g_strdelimit (fields[3], "_", '='); + g_base64_decode_inplace (fields[3], &outlen); + GST_TRACE ("info : %s", fields[3]); + info = gst_structure_from_string (fields[3], NULL); + if (info == NULL) + goto fail; + } else { + info = NULL; + } + + sample = gst_sample_new (gst_value_get_buffer (&bval), caps, + g_value_get_boxed (&sval), info); + + g_value_take_boxed (dest, sample); + + if (caps) + gst_caps_unref (caps); + + ret = TRUE; + +fail: + + g_value_unset (&bval); + g_value_unset (&sval); + +wrong_length: + + g_strfreev (fields); + + return ret; +} + /*********** * boolean * ***********/ @@ -5801,8 +5955,8 @@ _priv_gst_value_initialize (void) static GstValueTable gst_value = { 0, gst_value_compare_sample, - NULL, - NULL, + gst_value_serialize_sample, + gst_value_deserialize_sample, }; gst_value.type = GST_TYPE_SAMPLE; diff --git a/tests/check/gst/gsttag.c b/tests/check/gst/gsttag.c index 1e52a22..ed2e24b 100644 --- a/tests/check/gst/gsttag.c +++ b/tests/check/gst/gsttag.c @@ -566,6 +566,48 @@ GST_START_TEST (test_writability) GST_END_TEST; +/* this tests GstSample serialisation/deserialisation, esp. with multiple + * samples in a tag list */ +GST_START_TEST (test_serialization) +{ + GstTagList *tags, *tags2; + GstBuffer *b1, *b2; + GstSample *s1, *s2; + GstCaps *c2; + gchar *s; + + b1 = gst_buffer_new_allocate (NULL, 1, NULL); + gst_buffer_memset (b1, 0, 0xb3, -1); + s1 = gst_sample_new (b1, NULL, NULL, NULL); + gst_buffer_unref (b1); + + b2 = gst_buffer_new_allocate (NULL, 8, NULL); + gst_buffer_memset (b2, 0, 0x2f, -1); + c2 = gst_caps_new_empty_simple ("foo/bar"); + s2 = gst_sample_new (b2, c2, NULL, NULL); + gst_buffer_unref (b2); + gst_caps_unref (c2); + c2 = NULL; + + tags = gst_tag_list_new (GST_TAG_ATTACHMENT, s1, NULL); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT, s2, NULL); + GST_INFO ("tags: %" GST_PTR_FORMAT, tags); + + s = gst_tag_list_to_string (tags); + GST_INFO ("taglist -> string: %s", s); + tags2 = gst_tag_list_new_from_string (s); + GST_INFO ("string -> taglist: %" GST_PTR_FORMAT, tags2); + fail_unless (gst_tag_list_is_equal (tags, tags2)); + gst_tag_list_unref (tags2); + g_free (s); + + gst_sample_unref (s1); + gst_sample_unref (s2); + gst_tag_list_unref (tags); +} + +GST_END_TEST; + static Suite * gst_tag_suite (void) { @@ -585,6 +627,7 @@ gst_tag_suite (void) tcase_add_test (tc_chain, test_new_full); tcase_add_test (tc_chain, test_equal); tcase_add_test (tc_chain, test_writability); + tcase_add_test (tc_chain, test_serialization); return s; } -- 2.7.4