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/signals.h"
27 : #include "elements/common.h"
28 :
29 : typedef struct
30 : {
31 : const gchar* preset_name;
32 : union
33 : {
34 : struct
35 : {
36 : guint32 from_id;
37 : guint32 to_id;
38 : };
39 : guint32* ids;
40 : };
41 : } signal_info;
42 :
43 : #define GPAC_SIGNAL_ID_ARRAY(...) (guint32[]){ __VA_ARGS__, 0 }
44 : #define GPAC_SIGNAL_PRESET_RANGE(name, from, to) \
45 : { .preset_name = (name), .from_id = (from), .to_id = (to) }
46 : #define GPAC_SIGNAL_PRESET(name, ...) \
47 : { .preset_name = (name), .ids = GPAC_SIGNAL_ID_ARRAY(__VA_ARGS__) }
48 :
49 : static signal_info signal_presets[] = {
50 : GPAC_SIGNAL_PRESET_RANGE("dasher_all",
51 : GPAC_SIGNAL_DASHER_MANIFEST,
52 : GPAC_SIGNAL_DASHER_DELETE_SEGMENT),
53 : };
54 :
55 : void
56 25 : register_signal(GObjectClass* klass, GPAC_SignalId id)
57 : {
58 25 : g_assert(klass != NULL);
59 25 : g_assert(id < GPAC_SIGNAL_LAST);
60 25 : GstGpacParams* params = GST_GPAC_GET_PARAMS(klass);
61 25 : guint* registered_signals = params->registered_signals;
62 :
63 25 : if (registered_signals[id])
64 0 : return; // Already registered
65 :
66 25 : switch (id) {
67 20 : case GPAC_SIGNAL_DASHER_MANIFEST:
68 : case GPAC_SIGNAL_DASHER_MANIFEST_VARIANT:
69 : case GPAC_SIGNAL_DASHER_SEGMENT_INIT:
70 : case GPAC_SIGNAL_DASHER_SEGMENT:
71 40 : registered_signals[id] = g_signal_new(
72 20 : gpac_signal_names[id - 1], // Adjusted index for 0-based array
73 : G_TYPE_FROM_CLASS(klass),
74 : G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
75 : 0,
76 : NULL,
77 : NULL,
78 : NULL,
79 : G_TYPE_OUTPUT_STREAM,
80 : 1,
81 : G_TYPE_STRING);
82 20 : break;
83 :
84 5 : case GPAC_SIGNAL_DASHER_DELETE_SEGMENT:
85 10 : registered_signals[id] = g_signal_new(
86 5 : gpac_signal_names[id - 1], // Adjusted index for 0-based array
87 : G_TYPE_FROM_CLASS(klass),
88 : G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
89 : 0,
90 : NULL,
91 : NULL,
92 : NULL,
93 : G_TYPE_BOOLEAN, // Whether the segment was deleted
94 : 1,
95 : G_TYPE_STRING);
96 5 : break;
97 :
98 0 : default:
99 0 : break;
100 : };
101 : }
102 :
103 : void
104 2 : gpac_install_signals_by_presets(GObjectClass* gobject_class,
105 : const gchar* presets)
106 : {
107 2 : g_assert(gobject_class != NULL);
108 2 : g_assert(presets != NULL);
109 :
110 2 : gchar** preset_list = g_strsplit(presets, ",", -1);
111 4 : for (gint i = 0; preset_list[i] != NULL; i++) {
112 2 : const gchar* preset_name = g_strstrip(preset_list[i]);
113 2 : for (guint j = 0; j < G_N_ELEMENTS(signal_presets); j++) {
114 2 : if (g_strcmp0(signal_presets[j].preset_name, preset_name) == 0) {
115 2 : guint32 from = signal_presets[j].from_id;
116 2 : guint32 to = signal_presets[j].to_id;
117 2 : if (!from)
118 0 : from = GPAC_SIGNAL_START;
119 2 : if (!to)
120 0 : to = GPAC_SIGNAL_END;
121 :
122 12 : for (guint32 id = from; id <= to && id < GPAC_SIGNAL_LAST; id++) {
123 10 : register_signal(gobject_class, id);
124 : }
125 2 : break;
126 : }
127 : }
128 : }
129 2 : g_strfreev(preset_list);
130 2 : }
131 :
132 : void
133 3 : gpac_install_all_signals(GObjectClass* gobject_class)
134 : {
135 3 : g_assert(gobject_class != NULL);
136 :
137 18 : for (guint32 id = GPAC_SIGNAL_START; id < GPAC_SIGNAL_LAST; id++) {
138 15 : register_signal(gobject_class, id);
139 : }
140 3 : }
141 :
142 : gboolean
143 82 : gpac_signal_try_emit(GstElement* element,
144 : GPAC_SignalId id,
145 : const gchar* location,
146 : GOutputStream** output_stream)
147 : {
148 82 : g_assert(element != NULL);
149 82 : g_assert(id < GPAC_SIGNAL_LAST);
150 :
151 82 : GstObject* parent = GST_OBJECT(element);
152 : do {
153 164 : GObjectClass* klass = G_OBJECT_GET_CLASS(parent);
154 164 : GstGpacParams* params = GST_GPAC_GET_PARAMS(klass);
155 164 : guint* registered_signals = params->registered_signals;
156 :
157 : // We may not have registered this signal
158 164 : if (!registered_signals[id])
159 82 : continue;
160 :
161 82 : guint signal_id = registered_signals[id];
162 82 : if (signal_id) {
163 82 : if (output_stream) {
164 82 : *output_stream = NULL;
165 82 : g_signal_emit(parent, signal_id, 0, location, output_stream);
166 82 : return (*output_stream != NULL);
167 : }
168 :
169 0 : gboolean deleted = FALSE;
170 0 : g_signal_emit(parent, signal_id, 0, location, &deleted);
171 0 : return deleted;
172 : }
173 82 : } while ((parent = gst_element_get_parent(parent)));
174 :
175 0 : GST_DEBUG_OBJECT(element,
176 : "Signal %s not registered for element %s",
177 : gpac_signal_names[id - 1],
178 : GST_OBJECT_NAME(element));
179 :
180 0 : return FALSE;
181 : }
|