Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Deniz Ugur, Romain Bouqueau, Sohaib Larbi
5 : * Copyright (c) Motion Spell
6 : * All rights reserved
7 : *
8 : * This file is part of the GPAC/GStreamer wrapper
9 : *
10 : * This GPAC/GStreamer wrapper is free software; you can redistribute it
11 : * and/or modify it under the terms of the GNU Affero General Public License
12 : * as published by the Free Software Foundation; either version 3, or (at
13 : * your option) any later version.
14 : *
15 : * This GPAC/GStreamer wrapper is distributed in the hope that it will be
16 : * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Affero General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Affero General Public
21 : * License along with this library; see the file LICENSE. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include "lib/pid.h"
27 : #include "conversion/pid/registry.h"
28 : #include "gpacmessages.h"
29 :
30 : gboolean
31 21 : gpac_pid_apply_overrides(GPAC_PID_PROP_IMPL_ARGS_NO_ELEMENT, GList** to_skip)
32 : {
33 21 : GstStructure* caps = gst_caps_get_structure(priv->caps, 0);
34 21 : gchar* prefix = "gpac-";
35 21 : gboolean nested = FALSE;
36 :
37 21 : retry:
38 : // Go through the root structure
39 296 : for (gint i = 0; i < gst_structure_n_fields(caps); i++) {
40 275 : const gchar* field_name = gst_structure_nth_field_name(caps, i);
41 :
42 : // Check if the field name starts with the prefix
43 275 : if (g_str_has_prefix(field_name, prefix)) {
44 0 : GType type = gst_structure_get_field_type(caps, field_name);
45 0 : if (type != G_TYPE_STRING) {
46 0 : GST_WARNING_OBJECT(
47 : priv->self,
48 : "Property overrides for GPAC must be strings, %s is %s",
49 : field_name,
50 : g_type_name(type));
51 0 : continue;
52 : }
53 :
54 0 : const gchar* prop_name = field_name + strlen(prefix);
55 0 : u32 prop_4cc = gf_props_get_id(prop_name);
56 :
57 : // Parse the property value
58 0 : const GValue* value = gst_structure_get_value(caps, field_name);
59 0 : const gchar* prop_value = g_value_get_string(value);
60 :
61 : // Check if the property value is valid
62 0 : if (prop_value == NULL || prop_value[0] == '\0') {
63 0 : GST_WARNING_OBJECT(priv->self, "Empty value for %s", prop_name);
64 0 : continue;
65 : }
66 :
67 : // Set the property
68 0 : GF_PropertyValue pv = gf_props_parse_value(
69 : gf_props_4cc_get_type(prop_4cc), prop_name, prop_value, NULL, ',');
70 0 : gpac_return_val_if_fail(gf_filter_pid_set_property(pid, prop_4cc, &pv),
71 : FALSE);
72 :
73 : // Add the property to the to_skip list
74 0 : *to_skip = g_list_append(*to_skip, GUINT_TO_POINTER(prop_4cc));
75 : }
76 : }
77 :
78 : // If we have also processed nested structure, finish
79 21 : if (nested)
80 0 : goto finish;
81 :
82 : // Check if we have nested "gpac" structure
83 21 : if (gst_structure_has_field(caps, "gpac")) {
84 0 : if (!gst_structure_get(caps, "gpac", GST_TYPE_STRUCTURE, &caps, NULL)) {
85 0 : GST_ERROR_OBJECT(priv->self, "Failed to get nested gpac structure");
86 0 : return FALSE;
87 : }
88 0 : prefix = "";
89 0 : nested = TRUE;
90 0 : goto retry;
91 : }
92 :
93 21 : finish:
94 21 : return TRUE;
95 : }
96 :
97 : gboolean
98 21 : gpac_pid_reconfigure(GPAC_PID_PROP_IMPL_ARGS)
99 : {
100 : // Check arguments
101 21 : g_return_val_if_fail(element != NULL, FALSE);
102 21 : g_return_val_if_fail(priv != NULL, FALSE);
103 21 : g_return_val_if_fail(pid != NULL, FALSE);
104 :
105 : // Lock the element
106 42 : GST_OBJECT_AUTO_LOCK(element, auto_lock);
107 :
108 : // Go through overrides if caps are set
109 42 : g_autoptr(GList) to_skip = g_list_alloc();
110 21 : if (HAS_FLAG(priv->flags, GPAC_PAD_CAPS_SET)) {
111 21 : if (!gpac_pid_apply_overrides(priv, pid, &to_skip)) {
112 0 : GST_ERROR_OBJECT(priv->self, "Failed to apply overrides");
113 0 : return FALSE;
114 : }
115 : }
116 :
117 : // Go through the property registry
118 357 : for (u32 i = 0; i < gpac_pid_get_num_supported_props(); i++) {
119 336 : prop_registry_entry* entry = &prop_registry[i];
120 :
121 : // Skip the property if it is in the to_skip list
122 336 : if (g_list_find(to_skip, GUINT_TO_POINTER(entry->prop_4cc)))
123 0 : continue;
124 :
125 : // Try each handler
126 336 : if (entry->caps_handler != NULL)
127 462 : if (HAS_FLAG(priv->flags, GPAC_PAD_CAPS_SET) &&
128 231 : entry->caps_handler(element, priv, pid))
129 210 : continue;
130 :
131 126 : if (entry->tags_handler != NULL)
132 246 : if (HAS_FLAG(priv->flags, GPAC_PAD_TAGS_SET) &&
133 120 : entry->tags_handler(element, priv, pid))
134 35 : continue;
135 :
136 91 : if (entry->segment_handler != NULL)
137 42 : if (HAS_FLAG(priv->flags, GPAC_PAD_SEGMENT_SET) &&
138 21 : entry->segment_handler(element, priv, pid))
139 0 : continue;
140 :
141 91 : if (entry->query_handler != NULL)
142 21 : if (entry->query_handler(element, priv, pid))
143 21 : continue;
144 :
145 70 : if (entry->default_handler != NULL)
146 70 : if (entry->default_handler(priv, pid))
147 70 : continue;
148 :
149 : // If there were no flag set, we may not have all the information to
150 : // properly set the property
151 0 : if (priv->flags == 0)
152 0 : continue;
153 :
154 : // No handler was able to handle the property
155 0 : GST_ERROR_OBJECT(
156 : priv->self,
157 : "None of the handlers of %s (%s) were able to set the property",
158 : gf_props_4cc_get_name(entry->prop_4cc),
159 : gf_4cc_to_str(entry->prop_4cc));
160 0 : return FALSE;
161 : }
162 :
163 21 : return TRUE;
164 : }
165 :
166 : GF_FilterPid*
167 23 : gpac_pid_new(GPAC_SessionContext* sess)
168 : {
169 23 : GF_FilterPid* pid = gf_filter_pid_new(sess->memin);
170 23 : if (!pid) {
171 0 : GST_ELEMENT_ERROR(
172 : sess->element, LIBRARY, FAILED, (NULL), ("Failed to create new PID"));
173 0 : return NULL;
174 : }
175 23 : return pid;
176 : }
177 :
178 : void
179 0 : gpac_pid_del(GF_FilterPid* pid)
180 : {
181 0 : gf_filter_pid_remove(pid);
182 0 : }
|