--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "webrtc.h"
+#include "webrtc_private.h"
+
+typedef struct {
+ char *key;
+ GType type;
+} option_s;
+
+typedef struct _bundle_userdata {
+ option_s *avail_options;
+ const char *name;
+ GstStructure *structure;
+} bundle_userdata_s;
+
+static bool __is_supported_type(int bundle_type, GType g_type)
+{
+ switch (bundle_type) {
+ case BUNDLE_TYPE_STR:
+ if (g_type == G_TYPE_STRING)
+ return true;
+ break;
+ case BUNDLE_TYPE_BYTE:
+ if (g_type == G_TYPE_INT || g_type == G_TYPE_BOOLEAN)
+ return true;
+ break;
+ default:
+ LOG_ERROR("not supported bundle_type(%d)", bundle_type);
+ }
+
+ return false;
+}
+
+static bool __is_valid_size(GType g_type, size_t size)
+{
+ switch (g_type) {
+ case G_TYPE_BOOLEAN:
+ if (size != sizeof(bool)) {
+ LOG_ERROR("invalid size(%zu) for bool", size);
+ return false;
+ }
+ break;
+ case G_TYPE_INT:
+ if (size != sizeof(int)) {
+ LOG_ERROR("invalid size(%zu) for integer", size);
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static void __set_key_value(GstStructure *structure, const char *key, void *value, GType type, size_t size)
+{
+ RET_IF(structure == NULL, "structure is NULL");
+ RET_IF(key == NULL, "key is NULL");
+ RET_IF(value == NULL, "value is NULL");
+
+ if (!__is_valid_size(type, size))
+ return;
+
+ switch (type) {
+ case G_TYPE_BOOLEAN:
+ LOG_DEBUG("key[%s] value[%d] type[BOOLEAN] size[%zu]", key, *((bool*)value), size);
+ gst_structure_set(structure, key, type, *((bool*)value) ? TRUE : FALSE, NULL);
+ break;
+ case G_TYPE_INT:
+ LOG_DEBUG("key[%s] value[%d] type[INT] size[%zu]", key, *((int*)value), size);
+ gst_structure_set(structure, key, type, *((gint*)value), NULL);
+ break;
+ case G_TYPE_STRING:
+ LOG_DEBUG("key[%s] value[%s] type[STRING] size[%zu]", key, (char *)value, size);
+ gst_structure_set(structure, key, type, (gchar*)value, NULL);
+ break;
+ default:
+ LOG_ERROR("not supported GType(%d)", type);
+ }
+}
+
+static void __bundle_iter_cb(const char *key, const int type, const bundle_keyval_t *kv, void *user_data)
+{
+ int i;
+ bundle_userdata_s *data = (bundle_userdata_s *)user_data;
+ void *val = NULL;
+ size_t size = 0;
+
+ for (i = 0; data->avail_options[i].key; i++) {
+ if (g_strcmp0(key, data->avail_options[i].key))
+ continue;
+ if (!__is_supported_type(type, data->avail_options[i].type))
+ continue;
+ if (!data->structure)
+ data->structure = gst_structure_new_empty(data->name);
+
+ bundle_keyval_get_basic_val((bundle_keyval_t *)kv, &val, &size);
+ __set_key_value(data->structure, key, val, data->avail_options[i].type, size);
+ return;
+ }
+
+ LOG_ERROR("not supported key[%s] type[%d]", key, type);
+}
+
+static GstStructure* __get_matched_structure_from_bundle(bundle *options, option_s *avail_options, const char *name)
+{
+ bundle_userdata_s data = { avail_options, name, NULL };
+ gchar *result;
+
+ RET_VAL_IF(options == NULL, NULL, "options is NULL");
+ RET_VAL_IF(avail_options == NULL, NULL, "avail_options is NULL");
+ RET_VAL_IF(name == NULL, NULL, "name is NULL");
+
+ bundle_foreach(options, __bundle_iter_cb, &data);
+
+ RET_VAL_IF(data.structure == NULL, NULL, "structure is NULL");
+
+ result = gst_structure_to_string(data.structure);
+ LOG_INFO("%s", result);
+ g_free(result);
+
+ return data.structure;
+}