Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2017
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Compositor sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include <gpac/internal/compositor_dev.h>
27 : /*includes X3D nodes for WorldInfo, Inline and Key/String sensors*/
28 : #include <gpac/nodes_x3d.h>
29 : #include <gpac/nodes_svg.h>
30 : #include <gpac/options.h>
31 : #ifndef GPAC_DISABLE_VRML
32 :
33 : void InitMediaControl(GF_Scene *scene, GF_Node *node);
34 : void MC_Modified(GF_Node *node);
35 :
36 : void InitMediaSensor(GF_Scene *scene, GF_Node *node);
37 : void MS_Modified(GF_Node *node);
38 :
39 : void gf_init_inline(GF_Scene *scene, GF_Node *node);
40 : void gf_inline_on_modified(GF_Node *node);
41 :
42 : void gf_scene_init_storage(GF_Scene *scene, GF_Node *node);
43 :
44 :
45 40727 : void TraverseWorldInfo(GF_Node *node, void *rs, Bool is_destroy)
46 : {
47 40727 : GF_Scene *scene = (GF_Scene *)gf_node_get_private(node);
48 40727 : scene->world_info = is_destroy ? NULL : (M_WorldInfo *) node;
49 40727 : }
50 :
51 264 : void TraverseKeyNavigator(GF_Node *node, void *rs, Bool is_destroy)
52 : {
53 264 : if (is_destroy) {
54 4 : GF_Scene *scene = (GF_Scene *)gf_node_get_private(node);
55 4 : gf_list_del_item(scene->keynavigators, node);
56 4 : gf_sc_key_navigator_del(scene->compositor, node);
57 : }
58 264 : }
59 :
60 0 : void on_kn_set_focus(GF_Node*node, GF_Route *_route)
61 : {
62 0 : if (node) {
63 0 : GF_Scene *scene = (GF_Scene *)gf_node_get_private(node);
64 0 : gf_sc_change_key_navigator(scene->compositor, node);
65 : }
66 0 : }
67 :
68 1 : void evaluate_scene_cap(GF_Node *node, GF_Route *route)
69 : {
70 : GF_SystemRTInfo rti;
71 : Double fps;
72 : u32 height;
73 : Bool b_on;
74 : u32 b_charge, b_level;
75 :
76 : M_TermCap *tc = (M_TermCap *)node;
77 1 : GF_Scene *scene = gf_node_get_private(node);
78 1 : tc->value = 0;
79 1 : switch (tc->capability) {
80 1 : case 0: /*framerate*/
81 1 : fps = gf_sc_get_fps(scene->compositor, 1);
82 1 : if (fps<=5.0) tc->value = 1;
83 1 : else if (fps<=10.0) tc->value = 2;
84 1 : else if (fps<=20.0) tc->value = 3;
85 1 : else if (fps<=40.0) tc->value = 4;
86 0 : else tc->value = 5;
87 : break;
88 : case 1: /*colordepth*/
89 0 : return;
90 0 : case 2: /*screensize*/
91 0 : height = scene->compositor->display_height;
92 0 : if (height<200) tc->value = 1;
93 0 : else if (height<400) tc->value = 2;
94 0 : else if (height<800) tc->value = 3;
95 0 : else if (height<1600) tc->value = 4;
96 0 : else tc->value = 4;
97 : break;
98 : case 3: /*graphics hardware*/
99 : return;
100 : case 32:/*audio out format*/
101 : return;
102 : case 33:/*audio out format*/
103 : return;
104 : case 34:/*spatial audio cap*/
105 : return;
106 0 : case 64:/*CPU load*/
107 0 : if (!gf_sys_get_rti(200, &rti, 0) ) return;
108 0 : if (rti.total_cpu_usage<20) tc->value = 1;
109 0 : else if (rti.total_cpu_usage<40) tc->value = 2;
110 0 : else if (rti.total_cpu_usage<60) tc->value = 3;
111 0 : else if (rti.total_cpu_usage<80) tc->value = 4;
112 0 : else tc->value = 5;
113 : break;
114 0 : case 65:/*mem load*/
115 0 : if (!gf_sys_get_rti(200, &rti, GF_RTI_SYSTEM_MEMORY_ONLY) ) return;
116 0 : rti.physical_memory_avail /= 1024;
117 0 : if (rti.physical_memory_avail < 100) tc->value = 1;
118 0 : else if (rti.physical_memory_avail < 512) tc->value = 2;
119 0 : else if (rti.physical_memory_avail < 2048) tc->value = 3;
120 0 : else if (rti.physical_memory_avail < 8192) tc->value = 4;
121 0 : else if (rti.physical_memory_avail < 32768) tc->value = 5;
122 0 : else if (rti.physical_memory_avail < 204800) tc->value = 6;
123 0 : else tc->value = 7;
124 : break;
125 :
126 : /*GPAC extensions*/
127 0 : case 100: /*display width*/
128 0 : tc->value = scene->compositor->display_width;
129 0 : break;
130 0 : case 101: /*display height*/
131 0 : tc->value = scene->compositor->display_height;
132 0 : break;
133 0 : case 102: /*frame rate*/
134 0 : tc->value = (u32) gf_sc_get_fps(scene->compositor, 1);
135 0 : break;
136 0 : case 103: /*total CPU*/
137 0 : if (!gf_sys_get_rti(200, &rti, 0) ) return;
138 0 : tc->value = rti.total_cpu_usage;
139 0 : break;
140 0 : case 104: /*process CPU*/
141 0 : if (!gf_sys_get_rti(200, &rti, 0) ) return;
142 0 : tc->value = rti.process_cpu_usage;
143 0 : break;
144 0 : case 106: /*total memory in kB*/
145 0 : if (!gf_sys_get_rti(200, &rti, GF_RTI_SYSTEM_MEMORY_ONLY) ) return;
146 0 : tc->value = (u32) (rti.physical_memory/1024);
147 0 : break;
148 0 : case 107: /*total memory available in kB*/
149 0 : if (!gf_sys_get_rti(200, &rti, GF_RTI_SYSTEM_MEMORY_ONLY) ) return;
150 0 : tc->value = (u32) (rti.physical_memory_avail/1024);
151 0 : break;
152 0 : case 108: /*process memory in kB*/
153 0 : if (!gf_sys_get_rti(200, &rti, 0) ) return;
154 0 : tc->value = (u32) (rti.process_memory/1024);
155 0 : break;
156 0 : case 109: /*battery on/off*/
157 0 : gf_sys_get_battery_state(&b_on, &b_charge, &b_level, NULL, NULL);
158 0 : tc->value = b_on;
159 0 : break;
160 0 : case 110: /*battery charging*/
161 0 : gf_sys_get_battery_state(&b_on, &b_charge, &b_level, NULL, NULL);
162 0 : tc->value = b_charge;
163 0 : break;
164 0 : case 111: /*battery level*/
165 0 : gf_sys_get_battery_state(&b_on, &b_charge, &b_level, NULL, NULL);
166 0 : tc->value = b_level;
167 0 : break;
168 :
169 0 : case 112: /*audio vol*/
170 0 : tc->value = gf_sc_get_option(scene->compositor, GF_OPT_AUDIO_VOLUME);
171 0 : break;
172 0 : case 113: /*audio pan*/
173 0 : tc->value = gf_sc_get_option(scene->compositor, GF_OPT_AUDIO_PAN);
174 0 : break;
175 : default:
176 : return;
177 : }
178 1 : gf_node_event_out(node, 2);
179 : }
180 :
181 : static void InitTermCap(GF_Scene *scene, GF_Node *node)
182 : {
183 : M_TermCap *tc = (M_TermCap *)node;
184 1 : tc->on_evaluate = evaluate_scene_cap;
185 1 : gf_node_set_private(node, scene);
186 : /*evaluate upon init (cf BIFS spec)*/
187 1 : evaluate_scene_cap(node, NULL);
188 : }
189 :
190 : #endif /*GPAC_DISABLE_VRML*/
191 :
192 :
193 : #ifndef GPAC_DISABLE_SVG
194 1425 : static void svg_traverse_title(GF_Node *node, void *rs, Bool is_destroy)
195 : {
196 1425 : GF_Scene *scene = (GF_Scene *)gf_node_get_private(node);
197 1425 : scene->world_info = is_destroy ? NULL : node;
198 1425 : }
199 : #endif
200 :
201 : void gf_sc_on_node_init(GF_Compositor *sc, GF_Node *node);
202 :
203 32454 : void gf_scene_on_node_init(void *_scene, GF_Node *node)
204 : {
205 : GF_Scene *scene = (GF_Scene *)_scene;
206 32454 : if (!node || !scene) return;
207 :
208 32454 : switch (gf_node_get_tag(node)) {
209 : #ifndef GPAC_DISABLE_VRML
210 :
211 728 : case TAG_MPEG4_Inline:
212 : #ifndef GPAC_DISABLE_X3D
213 : case TAG_X3D_Inline:
214 : #endif
215 728 : gf_init_inline(scene, node);
216 728 : break;
217 : case TAG_MPEG4_MediaBuffer:
218 : break;
219 20 : case TAG_MPEG4_MediaControl:
220 20 : InitMediaControl(scene, node);
221 20 : break;
222 16 : case TAG_MPEG4_MediaSensor:
223 16 : InitMediaSensor(scene, node);
224 16 : break;
225 15 : case TAG_MPEG4_InputSensor:
226 15 : InitInputSensor(scene, node);
227 15 : break;
228 :
229 : /*BIFS nodes, get back to codec, but filter externProtos*/
230 : case TAG_MPEG4_Conditional:
231 : break;
232 : case TAG_MPEG4_QuantizationParameter:
233 : break;
234 : /*world info is stored at the inline scene level*/
235 381 : case TAG_MPEG4_WorldInfo:
236 : #ifndef GPAC_DISABLE_X3D
237 : case TAG_X3D_WorldInfo:
238 : #endif
239 381 : gf_node_set_callback_function(node, TraverseWorldInfo);
240 381 : gf_node_set_private(node, scene);
241 381 : break;
242 :
243 : #ifndef GPAC_DISABLE_X3D
244 1 : case TAG_X3D_KeySensor:
245 1 : InitKeySensor(scene, node);
246 1 : break;
247 1 : case TAG_X3D_StringSensor:
248 1 : InitStringSensor(scene, node);
249 1 : break;
250 : #endif
251 :
252 : case TAG_MPEG4_TermCap:
253 : InitTermCap(scene, node);
254 : break;
255 :
256 1 : case TAG_MPEG4_Storage:
257 1 : gf_scene_init_storage(scene, node);
258 1 : break;
259 :
260 4 : case TAG_MPEG4_KeyNavigator:
261 4 : gf_node_set_callback_function(node, TraverseKeyNavigator);
262 4 : gf_node_set_private(node, scene);
263 4 : gf_list_add(scene->keynavigators, node);
264 4 : ((M_KeyNavigator*)node)->on_setFocus = on_kn_set_focus;
265 : #ifdef GPAC_ENABLE_COVERAGE
266 4 : if (gf_sys_is_cov_mode()) {
267 : on_kn_set_focus(NULL, NULL);
268 : }
269 : #endif
270 : break;
271 :
272 : #endif
273 :
274 :
275 : #ifndef GPAC_DISABLE_SVG
276 62 : case TAG_SVG_title:
277 62 : gf_node_set_callback_function(node, svg_traverse_title);
278 62 : gf_node_set_private(node, scene);
279 62 : break;
280 : #endif
281 :
282 31188 : default:
283 31188 : gf_sc_on_node_init(scene->compositor, node);
284 31188 : break;
285 : }
286 : }
287 :
288 62256 : void gf_scene_on_node_modified(void *_is, GF_Node *node)
289 : {
290 : GF_Scene *scene = (GF_Scene *)_is;
291 62256 : if (!scene) return;
292 62256 : if (!node) {
293 2248 : gf_sc_invalidate(scene->compositor, NULL);
294 2248 : return;
295 : }
296 :
297 60008 : switch (gf_node_get_tag(node)) {
298 : #ifndef GPAC_DISABLE_VRML
299 91 : case TAG_MPEG4_Inline:
300 : #ifndef GPAC_DISABLE_X3D
301 : case TAG_X3D_Inline:
302 : #endif
303 91 : gf_inline_on_modified(node);
304 91 : break;
305 : case TAG_MPEG4_MediaBuffer:
306 : break;
307 28 : case TAG_MPEG4_MediaControl:
308 28 : MC_Modified(node);
309 28 : break;
310 1 : case TAG_MPEG4_MediaSensor:
311 1 : MS_Modified(node);
312 1 : break;
313 0 : case TAG_MPEG4_InputSensor:
314 0 : InputSensorModified(node);
315 0 : break;
316 : case TAG_MPEG4_Conditional:
317 : break;
318 : case TAG_MPEG4_Storage:
319 : break;
320 : #endif
321 59456 : default:
322 59456 : gf_sc_invalidate(scene->compositor, node);
323 59456 : break;
324 : }
325 : }
326 :
327 : static void gf_scene_on_node_destroyed(void *_is, GF_Node *node)
328 : {
329 : GF_Scene *scene = (GF_Scene *)_is;
330 37467 : if (!scene) return;
331 37467 : gf_sc_node_destroy(scene->compositor, node, NULL);
332 : }
333 :
334 : GF_EXPORT
335 160821 : void gf_scene_node_callback(void *_is, GF_SGNodeCbkType type, GF_Node *n, void *param)
336 : {
337 160821 : switch (type) {
338 62256 : case GF_SG_CALLBACK_MODIFIED:
339 62256 : gf_scene_on_node_modified(_is, n);
340 62256 : break;
341 : case GF_SG_CALLBACK_NODE_DESTROY:
342 : gf_scene_on_node_destroyed(_is, n);
343 : break;
344 32454 : case GF_SG_CALLBACK_INIT:
345 32454 : gf_scene_on_node_init(_is, n);
346 32454 : break;
347 : /*get all inline nodes using this subscene and bubble up...*/
348 28644 : case GF_SG_CALLBACK_GRAPH_DIRTY:
349 : {
350 28644 : u32 i=0;
351 : GF_Scene *scene = (GF_Scene *)_is;
352 28644 : if (scene->root_od->mo) {
353 : GF_Node *root;
354 3598 : while ((root=(GF_Node*)gf_mo_event_target_enum_node(scene->root_od->mo, &i))) {
355 2002 : gf_node_dirty_set(root, GF_SG_CHILD_DIRTY, GF_TRUE);
356 : }
357 : }
358 : }
359 28644 : break;
360 : }
361 160821 : }
|