Coverage Report

Created: 2026-01-23 07:37

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