| /* GStreamer | |
| * Copyright (C) 2022 Collabora Ltd | |
| * | |
| * analyticmeta.c | |
| * | |
| * 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., 51 Franklin St, Fifth Floor, | |
| * Boston, MA 02110-1301, USA. | |
| */ | |
| #include <gst/check/gstcheck.h> | |
| #include <gst/analytics/analytics.h> | |
| GST_START_TEST (test_add_classification_meta) | |
| { | |
| /* Verify we can create a relation metadata | |
| * and attach it classification mtd | |
| */ | |
| GstBuffer *buf; | |
| GstAnalyticsRelationMeta *rmeta; | |
| GstAnalyticsClsMtd cls_mtd; | |
| gfloat conf_lvl[] = { 0.5f, 0.5f }; | |
| GQuark class_quarks[2]; | |
| gboolean ret; | |
| class_quarks[0] = g_quark_from_string ("dog"); | |
| class_quarks[1] = g_quark_from_string ("cat"); | |
| buf = gst_buffer_new (); | |
| rmeta = gst_buffer_add_analytics_relation_meta (buf); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, conf_lvl, | |
| class_quarks, &cls_mtd); | |
| fail_unless (ret == TRUE); | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_meta_pooled) | |
| { | |
| GstBufferPool *pool; | |
| GstStructure *config; | |
| GstBuffer *buf; | |
| GstAnalyticsRelationMeta *rmeta1, *rmeta2; | |
| pool = gst_buffer_pool_new (); | |
| config = gst_buffer_pool_get_config (pool); | |
| gst_buffer_pool_config_set_params (config, NULL, 1, 1, 1); | |
| gst_buffer_pool_set_config (pool, config); | |
| gst_buffer_pool_set_active (pool, TRUE); | |
| gst_buffer_pool_acquire_buffer (pool, &buf, NULL); | |
| rmeta1 = gst_buffer_add_analytics_relation_meta (buf); | |
| gst_buffer_unref (buf); | |
| gst_buffer_pool_acquire_buffer (pool, &buf, NULL); | |
| rmeta2 = gst_buffer_add_analytics_relation_meta (buf); | |
| fail_unless (rmeta1 == rmeta2); | |
| gst_buffer_unref (buf); | |
| gst_object_unref (pool); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_classification_meta_classes) | |
| { | |
| /* Verify we can retrieve classification data | |
| * from the relation metadata | |
| */ | |
| GstBuffer *buf; | |
| GstAnalyticsRelationMeta *rmeta; | |
| gboolean ret; | |
| GQuark class_quarks[2]; | |
| GstAnalyticsClsMtd cls_mtd, cls_mtd2; | |
| class_quarks[0] = g_quark_from_string ("dog"); | |
| class_quarks[1] = g_quark_from_string ("cat"); | |
| buf = gst_buffer_new (); | |
| rmeta = gst_buffer_add_analytics_relation_meta (buf); | |
| gfloat conf_lvl[] = { 0.6f, 0.4f }; | |
| ret = gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, conf_lvl, | |
| class_quarks, &cls_mtd); | |
| fail_unless (ret == TRUE); | |
| fail_unless (gst_analytics_relation_get_length (rmeta) == 1); | |
| gint dogIndex = gst_analytics_cls_mtd_get_index_by_quark (&cls_mtd, | |
| class_quarks[0]); | |
| fail_unless (dogIndex == 0); | |
| gfloat confLvl = gst_analytics_cls_mtd_get_level (&cls_mtd, dogIndex); | |
| GST_LOG ("dog:%f", confLvl); | |
| assert_equals_float (confLvl, 0.6f); | |
| gint catIndex = gst_analytics_cls_mtd_get_index_by_quark (&cls_mtd, | |
| g_quark_from_string ("cat")); | |
| confLvl = gst_analytics_cls_mtd_get_level (&cls_mtd, catIndex); | |
| GST_LOG ("Cat:%f", confLvl); | |
| assert_equals_float (confLvl, 0.4f); | |
| assert_equals_int (gst_analytics_mtd_get_id ((GstAnalyticsMtd *) & cls_mtd), | |
| 0); | |
| conf_lvl[0] = 0.1f; | |
| conf_lvl[1] = 0.9f; | |
| ret = | |
| gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, conf_lvl, | |
| class_quarks, &cls_mtd2); | |
| fail_unless (ret == TRUE); | |
| fail_unless (gst_analytics_relation_get_length (rmeta) == 2); | |
| dogIndex = gst_analytics_cls_mtd_get_index_by_quark (&cls_mtd2, | |
| class_quarks[0]); | |
| confLvl = gst_analytics_cls_mtd_get_level (&cls_mtd2, dogIndex); | |
| assert_equals_float (confLvl, 0.1f); | |
| catIndex = gst_analytics_cls_mtd_get_index_by_quark (&cls_mtd2, | |
| class_quarks[0]); | |
| confLvl = gst_analytics_cls_mtd_get_level (&cls_mtd2, catIndex); | |
| assert_equals_float (confLvl, 0.1f); | |
| /* Verify the relation meta contain the correct number of relatable metadata */ | |
| fail_unless (gst_analytics_relation_get_length (rmeta) == 2); | |
| /* Verify first relatable metadata has the correct id. */ | |
| assert_equals_int (gst_analytics_mtd_get_id ((GstAnalyticsMtd *) & cls_mtd), | |
| 0); | |
| /* Verify second relatable metadata has the correct id. */ | |
| assert_equals_int (gst_analytics_mtd_get_id ( | |
| (GstAnalyticsMtd *) & cls_mtd2), 1); | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_add_relation_meta) | |
| { | |
| /* Verify we set a relation between relatable metadata. */ | |
| GstBuffer *buf; | |
| GstAnalyticsClsMtd cls_mtd[3]; | |
| GstAnalyticsRelationMetaInitParams init_params = { 5, 150 }; | |
| GstAnalyticsRelationMeta *relations; | |
| GQuark class_quarks[2]; | |
| gboolean ret; | |
| buf = gst_buffer_new (); | |
| relations = gst_buffer_add_analytics_relation_meta_full (buf, &init_params); | |
| gfloat conf_lvl[] = { 0.6f, 0.4f }; | |
| class_quarks[0] = g_quark_from_string ("dog"); | |
| class_quarks[1] = g_quark_from_string ("cat"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[0]); | |
| fail_unless (ret == TRUE); | |
| gst_analytics_mtd_get_id ((GstAnalyticsMtd *) | |
| & cls_mtd[0]); | |
| conf_lvl[0] = 0.6f; | |
| conf_lvl[1] = 0.4f; | |
| class_quarks[0] = g_quark_from_string ("plant"); | |
| class_quarks[1] = g_quark_from_string ("animal"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[1]); | |
| gst_analytics_mtd_get_id ((GstAnalyticsMtd *) | |
| & cls_mtd[1]); | |
| fail_unless (gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, | |
| cls_mtd[1].id) == TRUE); | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_add_relation_inefficiency_reporting_cases) | |
| { | |
| /* | |
| * Verify inefficiency of relation order is reported. | |
| */ | |
| GstBuffer *buf; | |
| GstAnalyticsClsMtd cls_mtd[3]; | |
| GstAnalyticsRelationMetaInitParams init_params = { 2, 10 }; | |
| GstAnalyticsRelationMeta *relations; | |
| gboolean ret; | |
| GQuark class_quarks[2]; | |
| buf = gst_buffer_new (); | |
| relations = gst_buffer_add_analytics_relation_meta_full (buf, &init_params); | |
| gfloat conf_lvl[] = { 0.6f, 0.4f }; | |
| class_quarks[0] = g_quark_from_string ("dog"); | |
| class_quarks[1] = g_quark_from_string ("cat"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[0]); | |
| fail_unless (gst_analytics_relation_get_length (relations) == 1); | |
| fail_unless (ret == TRUE); | |
| conf_lvl[0] = 0.6f; | |
| conf_lvl[1] = 0.4f; | |
| class_quarks[0] = g_quark_from_string ("plant"); | |
| class_quarks[1] = g_quark_from_string ("animal"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[1]); | |
| fail_unless (gst_analytics_relation_get_length (relations) == 2); | |
| fail_unless (ret == TRUE); | |
| conf_lvl[0] = 0.6f; | |
| conf_lvl[1] = 0.4f; | |
| class_quarks[0] = g_quark_from_string ("male"); | |
| class_quarks[1] = g_quark_from_string ("female"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[2]); | |
| fail_unless (gst_analytics_relation_get_length (relations) == 3); | |
| fail_unless (ret == TRUE); | |
| fail_unless (gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, cls_mtd[1].id) | |
| == TRUE); | |
| fail_unless (gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, cls_mtd[2].id) | |
| == TRUE); | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_query_relation_meta_cases) | |
| { | |
| /* Verify we can query existence of direct and indirect relation */ | |
| GstBuffer *buf; | |
| GstAnalyticsClsMtd cls_mtd[3]; | |
| GstAnalyticsRelationMetaInitParams init_params = { 2, 150 }; | |
| GstAnalyticsRelationMeta *relations; | |
| gboolean ret; | |
| GQuark class_quarks[2]; | |
| buf = gst_buffer_new (); | |
| relations = gst_buffer_add_analytics_relation_meta_full (buf, &init_params); | |
| gfloat conf_lvl[] = { 0.6f, 0.4f }; | |
| class_quarks[0] = g_quark_from_string ("dog"); | |
| class_quarks[1] = g_quark_from_string ("cat"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[0]); | |
| fail_unless (ret == TRUE); | |
| conf_lvl[0] = 0.6f; | |
| conf_lvl[1] = 0.4f; | |
| class_quarks[0] = g_quark_from_string ("plant"); | |
| class_quarks[1] = g_quark_from_string ("animal"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[1]); | |
| fail_unless (ret == TRUE); | |
| conf_lvl[0] = 0.6f; | |
| conf_lvl[1] = 0.4f; | |
| class_quarks[0] = g_quark_from_string ("male"); | |
| class_quarks[1] = g_quark_from_string ("female"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[2]); | |
| fail_unless (ret == TRUE); | |
| // Pet is part of kingdom | |
| gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, cls_mtd[1].id); | |
| // Kingdom contain pet | |
| gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, cls_mtd[1].id, cls_mtd[0].id); | |
| // Pet contain gender | |
| gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, cls_mtd[0].id, cls_mtd[2].id); | |
| /* Query if pet relate kingdom through a IS_PART relation with a maximum | |
| * relation span of 1. Max relation span of 1 mean they directly related.*/ | |
| gboolean exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id, | |
| cls_mtd[1].id, 1, GST_ANALYTICS_REL_TYPE_IS_PART_OF, NULL); | |
| fail_unless (exist == TRUE); | |
| /* Query if pet relate to gender through a IS_PART relation. */ | |
| exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id, | |
| cls_mtd[2].id, 1, GST_ANALYTICS_REL_TYPE_IS_PART_OF, NULL); | |
| fail_unless (exist == FALSE); | |
| /* Query if pet relate to kingdom through a CONTAIN relation. */ | |
| exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id, | |
| cls_mtd[1].id, 1, GST_ANALYTICS_REL_TYPE_CONTAIN, NULL); | |
| fail_unless (exist == FALSE); | |
| GstAnalyticsRelTypes cond = | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF | GST_ANALYTICS_REL_TYPE_CONTAIN | | |
| GST_ANALYTICS_REL_TYPE_RELATE_TO; | |
| /* Query if pet relate to gender through IS_PART or CONTAIN or | |
| * RELATE_TO relation. */ | |
| exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id, | |
| cls_mtd[2].id, 1, cond, NULL); | |
| fail_unless (exist == TRUE); | |
| /* Query if pet relate to kindom through CONTAIN or RELATE_TO relation */ | |
| cond = GST_ANALYTICS_REL_TYPE_CONTAIN | GST_ANALYTICS_REL_TYPE_RELATE_TO; | |
| exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id, | |
| cls_mtd[1].id, 1, cond, NULL); | |
| fail_unless (exist == FALSE); | |
| /* Query if kingdom relate to gender through a CONTAIN relation with a maximum | |
| * relation span of 1. */ | |
| exist = gst_analytics_relation_meta_exist (relations, cls_mtd[1].id, | |
| cls_mtd[2].id, 1, GST_ANALYTICS_REL_TYPE_CONTAIN, NULL); | |
| /* We expect this to fail because kingdom relate to gender CONTAIN relations | |
| * but indirectly (via pet) and we set the max relation span to 1*/ | |
| fail_unless (exist == FALSE); | |
| /* Same has previous check but using INFINIT relation span */ | |
| exist = gst_analytics_relation_meta_exist (relations, cls_mtd[1].id, | |
| cls_mtd[2].id, GST_INF_RELATION_SPAN, GST_ANALYTICS_REL_TYPE_CONTAIN, | |
| NULL); | |
| fail_unless (exist == TRUE); | |
| exist = gst_analytics_relation_meta_exist (relations, cls_mtd[2].id, | |
| cls_mtd[1].id, GST_INF_RELATION_SPAN, GST_ANALYTICS_REL_TYPE_CONTAIN, | |
| NULL); | |
| fail_unless (exist == FALSE); | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_path_relation_meta) | |
| { | |
| /* Verify we can retrieve relation path */ | |
| GstBuffer *buf; | |
| GstAnalyticsClsMtd cls_mtd[3]; | |
| GstAnalyticsRelationMetaInitParams init_params = { 2, 150 }; | |
| GstAnalyticsRelationMeta *relations; | |
| gboolean ret; | |
| GQuark class_quarks[2]; | |
| buf = gst_buffer_new (); | |
| relations = gst_buffer_add_analytics_relation_meta_full (buf, &init_params); | |
| gfloat conf_lvl[] = { 0.6f, 0.4f }; | |
| class_quarks[0] = g_quark_from_string ("dog"); | |
| class_quarks[1] = g_quark_from_string ("cat"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[0]); | |
| fail_unless (ret == TRUE); | |
| fail_unless (cls_mtd[0].id == 0); | |
| conf_lvl[0] = 0.6f; | |
| conf_lvl[1] = 0.4f; | |
| class_quarks[0] = g_quark_from_string ("plant"); | |
| class_quarks[1] = g_quark_from_string ("animal"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[1]); | |
| fail_unless (ret == TRUE); | |
| fail_unless (cls_mtd[1].id == 1); | |
| conf_lvl[0] = 0.6f; | |
| conf_lvl[1] = 0.4f; | |
| class_quarks[0] = g_quark_from_string ("male"); | |
| class_quarks[1] = g_quark_from_string ("female"); | |
| ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[2]); | |
| fail_unless (ret == TRUE); | |
| fail_unless (cls_mtd[2].id == 2); | |
| // Pet is part of kingdom | |
| gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, cls_mtd[1].id); | |
| // Kingdom contain pet | |
| gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, cls_mtd[1].id, cls_mtd[0].id); | |
| // Pet contain gender | |
| gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, cls_mtd[0].id, cls_mtd[2].id); | |
| GArray *path = NULL; | |
| GstAnalyticsRelTypes cond = GST_ANALYTICS_REL_TYPE_CONTAIN; | |
| gboolean exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id, | |
| cls_mtd[2].id, GST_INF_RELATION_SPAN, cond, &path); | |
| if (exist) { | |
| fail_unless (path != NULL); | |
| gint i; | |
| guint path_check_ids[] = { 0, 2 }; | |
| fail_unless (path->len == 2); | |
| for (i = 0; i < path->len; i++) { | |
| fail_unless (path_check_ids[i] == g_array_index (path, guint, i)); | |
| } | |
| g_array_free (g_steal_pointer (&path), TRUE); | |
| fail_unless (i == 2); | |
| } | |
| cond = GST_ANALYTICS_REL_TYPE_CONTAIN; | |
| exist = gst_analytics_relation_meta_exist (relations, cls_mtd[1].id, | |
| cls_mtd[2].id, GST_INF_RELATION_SPAN, cond, &path); | |
| if (exist) { | |
| gint i; | |
| guint path_check_ids[] = { 1, 0, 2 }; | |
| fail_unless (path != NULL); | |
| fail_unless (path->len == 3); | |
| for (i = 0; i < path->len; i++) { | |
| fail_unless (path_check_ids[i] == g_array_index (path, guint, i)); | |
| } | |
| g_array_free (g_steal_pointer (&path), TRUE); | |
| fail_unless (i == 3); | |
| } | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_cyclic_relation_meta) | |
| { | |
| /* Verify we can discover cycle in relation and not report multiple time | |
| * the same node and get into an infinit exploration */ | |
| GstBuffer *buf; | |
| GstAnalyticsClsMtd cls_mtd[3]; | |
| GstAnalyticsRelationMetaInitParams init_params = { 2, 150 }; | |
| GstAnalyticsRelationMeta *relations; | |
| gfloat conf_lvl[2]; | |
| GQuark class_quarks[2]; | |
| class_quarks[0] = g_quark_from_string ("attr1"); | |
| class_quarks[1] = g_quark_from_string ("attr2"); | |
| buf = gst_buffer_new (); | |
| relations = gst_buffer_add_analytics_relation_meta_full (buf, &init_params); | |
| conf_lvl[0] = 0.5f; | |
| conf_lvl[1] = 0.5f; | |
| gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[0]); | |
| gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[1]); | |
| gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl, | |
| class_quarks, &cls_mtd[2]); | |
| // (0) -> (1) | |
| gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, cls_mtd[1].id); | |
| // (1)->(2) | |
| gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[1].id, cls_mtd[2].id); | |
| // (2) -> (0) | |
| gst_analytics_relation_meta_set_relation (relations, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[2].id, cls_mtd[0].id); | |
| GArray *path = NULL; | |
| GstAnalyticsRelTypes cond = GST_ANALYTICS_REL_TYPE_CONTAIN; | |
| gboolean exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id, | |
| cls_mtd[2].id, GST_INF_RELATION_SPAN, cond, &path); | |
| fail_unless (exist == FALSE); | |
| cond = GST_ANALYTICS_REL_TYPE_IS_PART_OF; | |
| exist = | |
| gst_analytics_relation_meta_exist (relations, cls_mtd[0].id, | |
| cls_mtd[2].id, GST_INF_RELATION_SPAN, cond, &path); | |
| fail_unless (exist == TRUE); | |
| if (exist) { | |
| gint i; | |
| guint path_ids[] = { 0, 1, 2 }; | |
| fail_unless (path->len == 3); | |
| for (i = 0; i < path->len; i++) { | |
| fail_unless (path_ids[i] == g_array_index (path, guint, i)); | |
| } | |
| g_array_free (g_steal_pointer (&path), TRUE); | |
| fail_unless (i == 3); | |
| } | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_add_od_meta) | |
| { | |
| /* Verity we can add Object Detection relatable metadata to a relation | |
| * metadata */ | |
| GstBuffer *buf; | |
| GstAnalyticsRelationMetaInitParams init_params = { 5, 150 }; | |
| GstAnalyticsRelationMeta *rmeta; | |
| GstAnalyticsODMtd od_mtd; | |
| gboolean ret; | |
| buf = gst_buffer_new (); | |
| rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params); | |
| GQuark type = g_quark_from_string ("dog"); | |
| gint x = 20; | |
| gint y = 20; | |
| gint w = 10; | |
| gint h = 15; | |
| gfloat loc_conf_lvl = 0.6f; | |
| ret = gst_analytics_relation_meta_add_od_mtd (rmeta, type, x, y, | |
| w, h, loc_conf_lvl, &od_mtd); | |
| fail_unless (ret == TRUE); | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_od_meta_fields) | |
| { | |
| /* Verify we can readback fields of object detection metadata */ | |
| GstBuffer *buf; | |
| GstAnalyticsRelationMetaInitParams init_params = { 5, 150 }; | |
| GstAnalyticsRelationMeta *rmeta; | |
| GstAnalyticsODMtd od_mtd; | |
| gboolean ret; | |
| buf = gst_buffer_new (); | |
| rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params); | |
| GQuark type = g_quark_from_string ("dog"); | |
| gint x = 21; | |
| gint y = 20; | |
| gint w = 10; | |
| gint h = 15; | |
| gfloat loc_conf_lvl = 0.6f; | |
| ret = gst_analytics_relation_meta_add_od_mtd (rmeta, type, x, y, | |
| w, h, loc_conf_lvl, &od_mtd); | |
| fail_unless (ret == TRUE); | |
| gint _x, _y, _w, _h; | |
| gfloat _loc_conf_lvl; | |
| gst_analytics_od_mtd_get_location (&od_mtd, &_x, &_y, &_w, &_h, | |
| &_loc_conf_lvl); | |
| fail_unless (_x == x); | |
| fail_unless (_y == y); | |
| fail_unless (_w == w); | |
| fail_unless (_h == h); | |
| fail_unless (_loc_conf_lvl == loc_conf_lvl); | |
| _loc_conf_lvl = -200.0; // dirty this var by setting invalid value. | |
| gst_analytics_od_mtd_get_confidence_lvl (&od_mtd, &_loc_conf_lvl); | |
| fail_unless (_loc_conf_lvl == loc_conf_lvl); | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_od_cls_relation) | |
| { | |
| /* Verify we can add a object detection and classification metadata to | |
| * a relation metadata */ | |
| GstBuffer *buf; | |
| GstAnalyticsClsMtd cls_mtd; | |
| GstAnalyticsODMtd od_mtd; | |
| /* We intentionally set buffer small than required to verify sanity | |
| * with re-allocation */ | |
| GstAnalyticsRelationMetaInitParams init_params = { 5, 150 }; | |
| GstAnalyticsRelationMeta *rmeta; | |
| gboolean ret; | |
| GArray *path = NULL; | |
| gboolean exist; | |
| gint _x, _y, _w, _h; | |
| gfloat _loc_conf_lvl; | |
| GQuark class_quarks[2]; | |
| buf = gst_buffer_new (); | |
| rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params); | |
| gfloat conf_lvl[] = { 0.7f, 0.3f }; | |
| class_quarks[0] = g_quark_from_string ("dog"); | |
| class_quarks[1] = g_quark_from_string ("cat"); | |
| gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, conf_lvl, | |
| class_quarks, &cls_mtd); | |
| GQuark type = g_quark_from_string ("dog"); | |
| gint x = 21; | |
| gint y = 20; | |
| gint w = 10; | |
| gint h = 15; | |
| gfloat loc_conf_lvl = 0.6f; | |
| gst_analytics_relation_meta_add_od_mtd (rmeta, type, x, y, w, h, | |
| loc_conf_lvl, &od_mtd); | |
| ret = gst_analytics_relation_meta_set_relation (rmeta, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, od_mtd.id, cls_mtd.id); | |
| fail_unless (ret == TRUE); | |
| ret = gst_analytics_relation_meta_set_relation (rmeta, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd.id, od_mtd.id); | |
| fail_unless (ret == TRUE); | |
| /* Verify OD relate to CLS only through a CONTAIN relation */ | |
| exist = gst_analytics_relation_meta_exist (rmeta, | |
| od_mtd.id, cls_mtd.id, GST_INF_RELATION_SPAN, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, NULL); | |
| fail_unless (exist == FALSE); | |
| exist = gst_analytics_relation_meta_exist (rmeta, | |
| od_mtd.id, cls_mtd.id, GST_INF_RELATION_SPAN, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, &path); | |
| fail_unless (exist == TRUE); | |
| /* Query the relation path and verify it is correct */ | |
| guint ids[2]; | |
| gint i; | |
| fail_unless (path->len == 2); | |
| for (i = 0; i < path->len; i++) { | |
| ids[i] = g_array_index (path, guint, i); | |
| GST_LOG ("id=%u", ids[i]); | |
| } | |
| g_array_free (g_steal_pointer (&path), TRUE); | |
| fail_unless (ids[0] == 1); | |
| fail_unless (ids[1] == 0); | |
| GstAnalyticsMtd rlt_mtd; | |
| exist = gst_analytics_relation_meta_get_mtd (rmeta, ids[0], 0, &rlt_mtd); | |
| fail_unless (exist == TRUE); | |
| GstAnalyticsMtdType mtd_type = gst_analytics_mtd_get_mtd_type (&rlt_mtd); | |
| /* Verify relatable meta with id == 1 is of type Object Detection */ | |
| fail_unless (mtd_type == gst_analytics_od_mtd_get_mtd_type ()); | |
| gst_analytics_od_mtd_get_location ((GstAnalyticsODMtd *) & rlt_mtd, &_x, &_y, | |
| &_w, &_h, &_loc_conf_lvl); | |
| fail_unless (_x == x); | |
| fail_unless (_y == y); | |
| fail_unless (_w == w); | |
| fail_unless (_h == h); | |
| fail_unless (_loc_conf_lvl == loc_conf_lvl); | |
| GST_LOG ("mtd_type:%s", gst_analytics_mtd_type_get_name (mtd_type)); | |
| exist = gst_analytics_relation_meta_get_mtd (rmeta, ids[1], 0, &rlt_mtd); | |
| fail_unless (exist == TRUE); | |
| mtd_type = gst_analytics_mtd_get_mtd_type (&rlt_mtd); | |
| /* Verify relatable meta with id == 0 is of type classification */ | |
| fail_unless (mtd_type == gst_analytics_cls_mtd_get_mtd_type ()); | |
| gint index = | |
| gst_analytics_cls_mtd_get_index_by_quark ((GstAnalyticsClsMtd *) & | |
| rlt_mtd, | |
| g_quark_from_string ("dog")); | |
| gfloat lvl = | |
| gst_analytics_cls_mtd_get_level ((GstAnalyticsClsMtd *) & rlt_mtd, index); | |
| GST_LOG ("dog %f [%d, %d %d, %d", lvl, _x, _y, _w, _h); | |
| fail_unless (lvl == 0.7f); | |
| index = | |
| gst_analytics_cls_mtd_get_index_by_quark ((GstAnalyticsClsMtd *) & | |
| rlt_mtd, g_quark_from_string ("cat")); | |
| lvl = | |
| gst_analytics_cls_mtd_get_level ((GstAnalyticsClsMtd *) & rlt_mtd, index); | |
| fail_unless (lvl == 0.3f); | |
| GST_LOG ("mtd_type:%s", gst_analytics_mtd_type_get_name (mtd_type)); | |
| GST_LOG ("cat %f [%d, %d %d, %d", lvl, _x, _y, _w, _h); | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_multi_od_cls_relation) | |
| { | |
| GstBuffer *buf; | |
| GstAnalyticsClsMtd cls_mtd[3]; | |
| GstAnalyticsODMtd od_mtd[2]; | |
| GstAnalyticsRelationMetaInitParams init_params = { 5, 150 }; | |
| GstAnalyticsRelationMeta *rmeta; | |
| guint cls_id, ids[2], i; | |
| gboolean ret; | |
| const gint dog_cls_index = 0; | |
| const gint cat_cls_index = 1; | |
| gfloat cls_conf_lvl[2], lvl; | |
| GArray *path = NULL; | |
| gfloat _loc_conf_lvl; | |
| gint x, _x, y, _y, w, _w, h, _h; | |
| GstAnalyticsMtdType mtd_type; | |
| GQuark cls_type; | |
| GstAnalyticsMtd mtd; | |
| gpointer state = NULL; | |
| GQuark class_quarks[2]; | |
| class_quarks[0] = g_quark_from_string ("dog"); | |
| class_quarks[1] = g_quark_from_string ("cat"); | |
| buf = gst_buffer_new (); | |
| rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params); | |
| /* Define first relation ObjectDetection -contain-> Classification */ | |
| cls_conf_lvl[dog_cls_index] = 0.7f; | |
| cls_conf_lvl[cat_cls_index] = 0.3f; | |
| gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, cls_conf_lvl, | |
| class_quarks, &cls_mtd[0]); | |
| cls_type = g_quark_from_string ("dog"); | |
| x = 21; | |
| y = 20; | |
| w = 10; | |
| h = 15; | |
| gfloat loc_conf_lvl = 0.6f; | |
| gst_analytics_relation_meta_add_od_mtd (rmeta, cls_type, x, y, w, | |
| h, loc_conf_lvl, &od_mtd[0]); | |
| ret = gst_analytics_relation_meta_set_relation (rmeta, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, od_mtd[0].id, cls_mtd[0].id); | |
| fail_unless (ret == TRUE); | |
| GST_LOG ("Set rel Obj:%d -c-> Cls:%d", od_mtd[0].id, cls_mtd[0].id); | |
| /* Define second relation ObjectDetection -contain-> Classification */ | |
| cls_conf_lvl[dog_cls_index] = 0.1f; | |
| cls_conf_lvl[cat_cls_index] = 0.9f; | |
| gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, cls_conf_lvl, | |
| class_quarks, &cls_mtd[1]); | |
| cls_type = g_quark_from_string ("cat"); | |
| x = 50; | |
| y = 21; | |
| w = 11; | |
| h = 16; | |
| loc_conf_lvl = 0.7f; | |
| gst_analytics_relation_meta_add_od_mtd (rmeta, cls_type, x, y, w, | |
| h, loc_conf_lvl, &od_mtd[1]); | |
| ret = gst_analytics_relation_meta_set_relation (rmeta, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, od_mtd[1].id, cls_mtd[1].id); | |
| GST_LOG ("Set rel Obj:%d -c-> Cls:%d", od_mtd[1].id, cls_mtd[1].id); | |
| fail_unless (ret == TRUE); | |
| /* Query relations */ | |
| /* Query relation between first object detection and first classification | |
| * and verify they are only related by CONTAIN relation OD relate to | |
| * CLASSIFICATION through a CONTAIN relation. */ | |
| gboolean exist = | |
| gst_analytics_relation_meta_exist (rmeta, od_mtd[0].id, cls_mtd[0].id, | |
| GST_INF_RELATION_SPAN, | |
| GST_ANALYTICS_REL_TYPE_IS_PART_OF, NULL); | |
| fail_unless (exist == FALSE); | |
| exist = | |
| gst_analytics_relation_meta_exist (rmeta, od_mtd[0].id, cls_mtd[0].id, | |
| GST_INF_RELATION_SPAN, GST_ANALYTICS_REL_TYPE_CONTAIN, NULL); | |
| fail_unless (exist == TRUE); | |
| /* Query relation between second object detection and second classification | |
| * and verify they are only related by CONTAIN relation OD relate to | |
| * CLASSIFICATION through a CONTAIN relation. | |
| */ | |
| exist = | |
| gst_analytics_relation_meta_exist (rmeta, od_mtd[1].id, cls_mtd[1].id, | |
| GST_INF_RELATION_SPAN, GST_ANALYTICS_REL_TYPE_CONTAIN, &path); | |
| fail_unless (exist == TRUE); | |
| /* Verify relation path between OD second (id=3) and Cls second (id=2) | |
| * is correct | |
| */ | |
| fail_unless (path->len == 2); | |
| for (i = 0; i < path->len; i++) { | |
| ids[i] = g_array_index (path, guint, i); | |
| GST_LOG ("id=%u", ids[i]); | |
| } | |
| g_array_free (g_steal_pointer (&path), TRUE); | |
| fail_unless (ids[0] == 3); | |
| fail_unless (ids[1] == 2); | |
| /* Verify the relatable metadata 3 is of correct type | |
| * (ObjectDetection). Verify it describe the correct | |
| * the correct data. | |
| */ | |
| gst_analytics_relation_meta_get_mtd (rmeta, ids[0], 0, &mtd); | |
| mtd_type = gst_analytics_mtd_get_mtd_type (&mtd); | |
| fail_unless (mtd_type == gst_analytics_od_mtd_get_mtd_type ()); | |
| gst_analytics_od_mtd_get_location ((GstAnalyticsODMtd *) & mtd, &_x, &_y, &_w, | |
| &_h, &_loc_conf_lvl); | |
| fail_unless (_x == 50); | |
| fail_unless (_y == 21); | |
| fail_unless (_w == 11); | |
| fail_unless (_h == 16); | |
| fail_unless (_loc_conf_lvl == 0.7f); | |
| GST_LOG ("mtd_type:%s", gst_analytics_mtd_type_get_name (mtd_type)); | |
| /* Verify the relatable metadata 2 is of correct type | |
| * (ObjectDetection). | |
| */ | |
| gst_analytics_relation_meta_get_mtd (rmeta, ids[1], 0, &mtd); | |
| mtd_type = gst_analytics_mtd_get_mtd_type (&mtd); | |
| fail_unless (mtd_type == gst_analytics_cls_mtd_get_mtd_type ()); | |
| /* Verify data of the CLASSIFICATION retrieved */ | |
| gint index = | |
| gst_analytics_cls_mtd_get_index_by_quark ((GstAnalyticsClsMtd *) & mtd, | |
| g_quark_from_string ("dog")); | |
| lvl = gst_analytics_cls_mtd_get_level ((GstAnalyticsClsMtd *) & mtd, index); | |
| GST_LOG ("dog %f [%d, %d %d, %d", lvl, _x, _y, _w, _h); | |
| fail_unless (lvl == 0.1f); | |
| /* Verify data of the CLASSIFICATION retrieved */ | |
| index = | |
| gst_analytics_cls_mtd_get_index_by_quark ((GstAnalyticsClsMtd *) & mtd, | |
| g_quark_from_string ("cat")); | |
| lvl = gst_analytics_cls_mtd_get_level ((GstAnalyticsClsMtd *) & mtd, index); | |
| GST_LOG ("mtd_type:%s", gst_analytics_mtd_type_get_name (mtd_type)); | |
| GST_LOG ("cat %f [%d, %d %d, %d", lvl, _x, _y, _w, _h); | |
| fail_unless (lvl == 0.9f); | |
| /* Retrieve relatable metadata related to the first object detection | |
| * through a CONTAIN relation of type CLASSIFICATION | |
| * Verify it's the first classification metadata | |
| */ | |
| gst_analytics_relation_meta_get_direct_related (rmeta, od_mtd[0].id, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, gst_analytics_cls_mtd_get_mtd_type (), | |
| &state, &mtd); | |
| cls_id = gst_analytics_mtd_get_id (&mtd); | |
| GST_LOG ("Obj:%d -> Cls:%d", od_mtd[0].id, cls_id); | |
| fail_unless (cls_id == cls_mtd[0].id); | |
| state = NULL; | |
| /* Retrieve relatable metadata related to the second object detection | |
| * through a CONTAIN relation of type CLASSIFICATION | |
| * Verify it's the first classification metadata | |
| */ | |
| gst_analytics_relation_meta_get_direct_related (rmeta, od_mtd[1].id, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, gst_analytics_cls_mtd_get_mtd_type (), | |
| &state, &mtd); | |
| cls_id = gst_analytics_mtd_get_id (&mtd); | |
| GST_LOG ("Obj:%d -> Cls:%d", od_mtd[1].id, cls_id); | |
| fail_unless (cls_id == cls_mtd[1].id); | |
| cls_conf_lvl[dog_cls_index] = 0.2f; | |
| cls_conf_lvl[cat_cls_index] = 0.8f; | |
| class_quarks[0] = g_quark_from_string ("canine"); | |
| class_quarks[1] = g_quark_from_string ("feline"); | |
| gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, cls_conf_lvl, | |
| class_quarks, &cls_mtd[2]); | |
| ret = gst_analytics_relation_meta_set_relation (rmeta, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, od_mtd[1].id, cls_mtd[2].id); | |
| state = NULL; | |
| ret = gst_analytics_relation_meta_get_direct_related (rmeta, od_mtd[1].id, | |
| GST_ANALYTICS_REL_TYPE_CONTAIN, gst_analytics_od_mtd_get_mtd_type (), | |
| &state, &mtd); | |
| fail_unless (ret == FALSE); | |
| gst_buffer_unref (buf); | |
| } | |
| GST_END_TEST; | |
| GST_START_TEST (test_add_tracking_meta) | |
| { | |
| /* Verify we can add tracking relatable meta to relation meta */ | |
| GstBuffer *buf1, *buf2; | |
| GstAnalyticsRelationMetaInitParams init_params = { 5, 150 }; | |
| GstAnalyticsRelationMeta *rmeta; | |
| GstAnalyticsTrackingMtd tracking_mtd; | |
| guint tracking_id; | |
| GstClockTime tracking_observation_time_1; | |
| gboolean ret; | |
| /* Verify we can add multiple trackings to relation metadata | |
| */ | |
| buf1 = gst_buffer_new (); | |
| rmeta = gst_buffer_add_analytics_relation_meta_full (buf1, &init_params); | |
| tracking_id = 1; | |
| tracking_observation_time_1 = GST_BUFFER_TIMESTAMP (buf1); | |
| ret = gst_analytics_relation_meta_add_tracking_mtd (rmeta, tracking_id, | |
| tracking_observation_time_1, &tracking_mtd); | |
| fail_unless (ret == TRUE); | |
| gst_buffer_unref (buf1); | |
| buf2 = gst_buffer_new (); | |
| rmeta = gst_buffer_add_analytics_relation_meta_full (buf2, &init_params); | |
| tracking_id = 1; | |
| ret = gst_analytics_relation_meta_add_tracking_mtd (rmeta, tracking_id, | |
| tracking_observation_time_1, &tracking_mtd); | |
| fail_unless (ret == TRUE); | |
| gst_buffer_unref (buf2); | |
| } | |
| GST_END_TEST; | |
| static Suite * | |
| analyticmeta_suite (void) | |
| { | |
| Suite *s; | |
| TCase *tc_chain_cls; | |
| TCase *tc_chain_relation; | |
| TCase *tc_chain_od; | |
| TCase *tc_chain_od_cls; | |
| TCase *tc_chain_tracking; | |
| s = suite_create ("Analytic Meta Library"); | |
| tc_chain_cls = tcase_create ("Classification Mtd"); | |
| suite_add_tcase (s, tc_chain_cls); | |
| tcase_add_test (tc_chain_cls, test_add_classification_meta); | |
| tcase_add_test (tc_chain_cls, test_classification_meta_classes); | |
| tcase_add_test (tc_chain_cls, test_meta_pooled); | |
| tc_chain_relation = tcase_create ("Relation Meta"); | |
| suite_add_tcase (s, tc_chain_relation); | |
| tcase_add_test (tc_chain_relation, test_add_relation_meta); | |
| tcase_add_test (tc_chain_relation, | |
| test_add_relation_inefficiency_reporting_cases); | |
| tcase_add_test (tc_chain_relation, test_query_relation_meta_cases); | |
| tcase_add_test (tc_chain_relation, test_path_relation_meta); | |
| tcase_add_test (tc_chain_relation, test_cyclic_relation_meta); | |
| tc_chain_od = tcase_create ("Object Detection Mtd"); | |
| suite_add_tcase (s, tc_chain_od); | |
| tcase_add_test (tc_chain_od, test_add_od_meta); | |
| tcase_add_test (tc_chain_od, test_od_meta_fields); | |
| tc_chain_od_cls = tcase_create ("Object Detection <-> Classification Mtd"); | |
| suite_add_tcase (s, tc_chain_od_cls); | |
| tcase_add_test (tc_chain_od_cls, test_od_cls_relation); | |
| tcase_add_test (tc_chain_od_cls, test_multi_od_cls_relation); | |
| tc_chain_tracking = tcase_create ("Tracking Mtd"); | |
| suite_add_tcase (s, tc_chain_tracking); | |
| tcase_add_test (tc_chain_tracking, test_add_tracking_meta); | |
| return s; | |
| } | |
| GST_CHECK_MAIN (analyticmeta); |