Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Management 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/scene_manager.h>
27 : #include <gpac/constants.h>
28 : #include <gpac/internal/scenegraph_dev.h>
29 :
30 : #ifndef GPAC_DISABLE_SCENE_STATS
31 :
32 : struct _statman
33 : {
34 : GF_SceneStatistics *stats;
35 : GF_List *def_nodes;
36 : };
37 :
38 24 : static GF_SceneStatistics *NewSceneStats()
39 : {
40 : GF_SceneStatistics *tmp;
41 24 : GF_SAFEALLOC(tmp, GF_SceneStatistics);
42 24 : if (!tmp) return NULL;
43 :
44 24 : tmp->node_stats = gf_list_new();
45 24 : tmp->proto_stats = gf_list_new();
46 :
47 24 : tmp->max_2d.x = FIX_MIN;
48 24 : tmp->max_2d.y = FIX_MIN;
49 24 : tmp->max_3d.x = FIX_MIN;
50 24 : tmp->max_3d.y = FIX_MIN;
51 24 : tmp->max_3d.z = FIX_MIN;
52 24 : tmp->min_2d.x = FIX_MAX;
53 24 : tmp->min_2d.y = FIX_MAX;
54 24 : tmp->min_3d.x = FIX_MAX;
55 24 : tmp->min_3d.y = FIX_MAX;
56 24 : tmp->min_3d.z = FIX_MAX;
57 24 : return tmp;
58 : }
59 :
60 69 : static void ResetStatisitics(GF_SceneStatistics *stat)
61 : {
62 900 : while (gf_list_count(stat->node_stats)) {
63 762 : GF_NodeStats *ptr = (GF_NodeStats *)gf_list_get(stat->node_stats, 0);
64 762 : gf_list_rem(stat->node_stats, 0);
65 762 : gf_free(ptr);
66 : }
67 87 : while (gf_list_count(stat->proto_stats)) {
68 18 : GF_NodeStats *ptr = (GF_NodeStats *)gf_list_get(stat->proto_stats, 0);
69 18 : gf_list_rem(stat->proto_stats, 0);
70 18 : gf_free(ptr);
71 : }
72 69 : stat->max_2d.x = FIX_MIN;
73 69 : stat->max_2d.y = FIX_MIN;
74 69 : stat->max_3d.x = FIX_MIN;
75 69 : stat->max_3d.y = FIX_MIN;
76 69 : stat->max_3d.z = FIX_MIN;
77 69 : stat->min_2d.x = FIX_MAX;
78 69 : stat->min_2d.y = FIX_MAX;
79 69 : stat->min_3d.x = FIX_MAX;
80 69 : stat->min_3d.y = FIX_MAX;
81 69 : stat->min_3d.z = FIX_MAX;
82 69 : stat->count_2d = stat->rem_2d = stat->count_3d = stat->rem_3d = stat->count_float = 0;
83 69 : stat->rem_float = stat->count_color = stat->rem_color = stat->count_2f = stat->count_3f = 0;
84 69 : }
85 :
86 24 : static void DeleteStatisitics(GF_SceneStatistics *stat)
87 : {
88 24 : ResetStatisitics(stat);
89 24 : gf_list_del(stat->node_stats);
90 24 : gf_list_del(stat->proto_stats);
91 24 : gf_free(stat);
92 24 : }
93 :
94 2247 : static void StatNode(GF_SceneStatistics *stat, GF_Node *n, Bool isUsed, Bool isDelete, GF_Node *prev)
95 : {
96 : u32 i;
97 : GF_NodeStats *ptr = NULL;
98 2247 : if (!stat) return;
99 :
100 2247 : if (n->sgprivate->tag == TAG_ProtoNode) {
101 : #ifndef GPAC_DISABLE_VRML
102 : GF_ProtoInstance *pr = (GF_ProtoInstance *)n;
103 24 : i=0;
104 66 : while ((ptr = (GF_NodeStats *)gf_list_enum(stat->proto_stats, &i))) {
105 24 : if (pr->proto_interface && (pr->proto_interface->ID == ptr->tag)) break;
106 : ptr = NULL;
107 : }
108 24 : if (!ptr) {
109 18 : GF_SAFEALLOC(ptr, GF_NodeStats);
110 18 : if (!ptr) return;
111 :
112 18 : if (pr->proto_interface) {
113 18 : ptr->tag = pr->proto_interface->ID;
114 18 : ptr->name = gf_sg_proto_get_class_name(pr->proto_interface);
115 : }
116 18 : gf_list_add(stat->proto_stats, ptr);
117 : }
118 : #endif
119 : } else {
120 2223 : i=0;
121 36693 : while ((ptr = (GF_NodeStats *)gf_list_enum(stat->node_stats, &i))) {
122 33708 : if (n->sgprivate->tag == ptr->tag) break;
123 : ptr = NULL;
124 : }
125 2223 : if (!ptr) {
126 762 : GF_SAFEALLOC(ptr, GF_NodeStats);
127 762 : if (!ptr) return;
128 762 : ptr->tag = n->sgprivate->tag;
129 762 : ptr->name = gf_node_get_class_name(n);
130 762 : gf_list_add(stat->node_stats, ptr);
131 : }
132 : }
133 2247 : if (isDelete) ptr->nb_del += n->sgprivate->num_instances;
134 2235 : else if (isUsed) ptr->nb_used += 1;
135 : /*this is because the node passes twice in the stat, once on DumpNode and once in replaceALL*/
136 2193 : else ptr->nb_created += prev ? (prev->sgprivate->num_instances - 1) : 1;
137 : }
138 :
139 : #ifndef GPAC_DISABLE_SVG
140 :
141 14196 : static void StatFixed(GF_SceneStatistics *stat, Fixed v, Bool scale)
142 : {
143 : u32 int_res, frac_res;
144 14196 : if (v > 32767.0)
145 : v = 32767.0;
146 14192 : else if (v < -32768.0)
147 : v = -32768.0;
148 :
149 14196 : u32 fixv = FIX2INT((v>0?v:-v) * (1<<16));
150 14196 : s32 intv = (fixv & 0xFFFF0000)>>16;
151 14196 : u32 fracv = fixv & 0x0000FFFF;
152 :
153 : int_res = 0;
154 14196 : while ( (intv >> int_res) ) int_res++;
155 14196 : int_res++; /* signedness */
156 :
157 14196 : if (fracv) {
158 : frac_res = 1;
159 162000 : while ((fracv << frac_res) & 0x0000FFFF)
160 151141 : frac_res++;
161 : } else {
162 : frac_res = 0;
163 : }
164 :
165 14196 : if (scale) {
166 96 : if (int_res > stat->scale_int_res_2d) stat->scale_int_res_2d = int_res;
167 96 : if (frac_res > stat->scale_frac_res_2d) stat->scale_frac_res_2d = frac_res;
168 : } else {
169 14100 : if (int_res > stat->int_res_2d) stat->int_res_2d = int_res;
170 14100 : if (frac_res > stat->frac_res_2d) stat->frac_res_2d = frac_res;
171 : }
172 14196 : if (stat->max_fixed < v) stat->max_fixed = v;
173 14196 : if (stat->min_fixed > v) stat->min_fixed = v;
174 14196 : }
175 :
176 :
177 6773 : static void StatSVGPoint(GF_SceneStatistics *stat, SFVec2f *val)
178 : {
179 6773 : if (!stat) return;
180 6773 : if (stat->max_2d.x < val->x) stat->max_2d.x = val->x;
181 6773 : if (stat->max_2d.y < val->y) stat->max_2d.y = val->y;
182 6773 : if (stat->min_2d.x > val->x) stat->min_2d.x = val->x;
183 6773 : if (stat->min_2d.y > val->y) stat->min_2d.y = val->y;
184 6773 : StatFixed(stat, val->x, 0);
185 6773 : StatFixed(stat, val->y, 0);
186 : }
187 : #endif
188 :
189 : static void StatSFVec2f(GF_SceneStatistics *stat, SFVec2f *val)
190 : {
191 468 : if (!stat) return;
192 636 : if (stat->max_2d.x < val->x) stat->max_2d.x = val->x;
193 636 : if (stat->max_2d.y < val->y) stat->max_2d.y = val->y;
194 636 : if (stat->min_2d.x > val->x) stat->min_2d.x = val->x;
195 636 : if (stat->min_2d.y > val->y) stat->min_2d.y = val->y;
196 : }
197 :
198 264 : static void StatSFVec3f(GF_SceneStatistics *stat, SFVec3f *val)
199 : {
200 264 : if (!stat) return;
201 264 : if (stat->max_3d.x < val->x) stat->max_3d.x = val->x;
202 264 : if (stat->max_3d.y < val->y) stat->max_3d.y = val->y;
203 264 : if (stat->max_3d.z < val->z) stat->max_3d.z = val->y;
204 264 : if (stat->min_3d.x > val->x) stat->min_3d.x = val->x;
205 264 : if (stat->min_3d.y > val->y) stat->min_3d.y = val->y;
206 264 : if (stat->min_3d.z > val->z) stat->min_3d.z = val->z;
207 : }
208 :
209 1056 : static void StatField(GF_SceneStatistics *stat, GF_FieldInfo *field)
210 : {
211 : u32 i;
212 :
213 1056 : switch (field->fieldType) {
214 182 : case GF_SG_VRML_SFFLOAT:
215 182 : stat->count_float++;
216 182 : if (stat->max_fixed < *(SFFloat*)field->far_ptr)
217 30 : stat->max_fixed = *(SFFloat*)field->far_ptr;
218 182 : if (stat->min_fixed > *(SFFloat*)field->far_ptr)
219 6 : stat->min_fixed = *(SFFloat*)field->far_ptr;
220 : break;
221 96 : case GF_SG_VRML_SFCOLOR:
222 96 : stat->count_color++;
223 : break;
224 168 : case GF_SG_VRML_SFVEC2F:
225 168 : stat->count_2f++;
226 168 : StatSFVec2f(stat, field->far_ptr);
227 : break;
228 36 : case GF_SG_VRML_SFVEC3F:
229 36 : stat->count_3f++;
230 36 : StatSFVec3f(stat, field->far_ptr);
231 : break;
232 :
233 42 : case GF_SG_VRML_MFFLOAT:
234 42 : stat->count_float+= ((MFFloat *)field->far_ptr)->count;
235 : break;
236 36 : case GF_SG_VRML_MFCOLOR:
237 36 : stat->count_color+= ((MFColor *)field->far_ptr)->count;
238 : break;
239 66 : case GF_SG_VRML_MFVEC2F:
240 : {
241 66 : MFVec2f *mf2d = (MFVec2f *)field->far_ptr;
242 438 : for (i=0; i<mf2d->count; i++) {
243 438 : StatSFVec2f(stat, &mf2d->vals[i]);
244 438 : stat->count_2d ++;
245 : }
246 : }
247 : break;
248 30 : case GF_SG_VRML_MFVEC3F:
249 : {
250 30 : MFVec3f *mf3d = (MFVec3f *)field->far_ptr;
251 228 : for (i=0; i<mf3d->count; i++) {
252 228 : StatSFVec3f(stat, &mf3d->vals[i]);
253 228 : stat->count_3d ++;
254 : }
255 : }
256 : break;
257 : }
258 1056 : }
259 :
260 :
261 54 : static void StatSingleField(GF_SceneStatistics *stat, GF_FieldInfo *field)
262 : {
263 54 : switch (field->fieldType) {
264 30 : case GF_SG_VRML_SFVEC2F:
265 30 : StatSFVec2f(stat, (SFVec2f *)field->far_ptr);
266 : break;
267 0 : case GF_SG_VRML_MFVEC3F:
268 0 : StatSFVec3f(stat, (SFVec3f *)field->far_ptr);
269 : break;
270 : }
271 54 : }
272 :
273 : #ifndef GPAC_DISABLE_SVG
274 2744 : static void StatSVGAttribute(GF_SceneStatistics *stat, GF_FieldInfo *field)
275 : {
276 : u32 i = 0;
277 :
278 2744 : stat->nb_svg_attributes++;
279 :
280 2744 : switch (field->fieldType) {
281 259 : case SVG_PathData_datatype:
282 : {
283 : #if USE_GF_PATH
284 259 : SVG_PathData *d = (SVG_PathData *)field->far_ptr;
285 6455 : for (i=0; i<d->n_points; i++) {
286 6455 : StatSVGPoint(stat, &(d->points[i]));
287 6455 : stat->count_2d ++;
288 : }
289 : #else
290 : SVG_PathData *d = (SVG_PathData *)field->far_ptr;
291 : for (i=0; i<gf_list_count(d->points); i++) {
292 : SVG_Point *p = (SVG_Point *)gf_list_get(d->points, i);
293 : StatSVGPoint(stat, (SFVec2f *)p);
294 : stat->count_2d ++;
295 : }
296 : #endif
297 : }
298 : break;
299 17 : case SVG_ViewBox_datatype:
300 : {
301 17 : SVG_ViewBox *vB = (SVG_ViewBox *)field->far_ptr;
302 17 : StatFixed(stat, vB->x, 0);
303 17 : StatFixed(stat, vB->y, 0);
304 17 : StatFixed(stat, vB->width, 0);
305 17 : StatFixed(stat, vB->height, 0);
306 : }
307 : break;
308 259 : case SVG_Points_datatype:
309 : case SVG_Coordinates_datatype:
310 : {
311 259 : GF_List *points = *((GF_List **)field->far_ptr);
312 318 : for (i=0; i<gf_list_count(points); i++) {
313 318 : SVG_Point *p = (SVG_Point *)gf_list_get(points, i);
314 318 : StatSVGPoint(stat, (SFVec2f *)p);
315 318 : stat->count_2d ++;
316 : }
317 : }
318 : break;
319 27 : case SVG_Transform_datatype:
320 : {
321 27 : GF_Matrix2D *mx = &((SVG_Transform *)field->far_ptr)->mat;
322 27 : if (!gf_mx2d_is_identity(*mx) && !(!mx->m[0] && !mx->m[1] && !mx->m[3] && !mx->m[4])) {
323 24 : StatFixed(stat, mx->m[0], 1);
324 24 : StatFixed(stat, mx->m[1], 1);
325 24 : StatFixed(stat, mx->m[3], 1);
326 24 : StatFixed(stat, mx->m[4], 1);
327 24 : StatFixed(stat, mx->m[2], 0);
328 24 : StatFixed(stat, mx->m[5], 0);
329 : }
330 : }
331 : break;
332 0 : case SVG_Motion_datatype:
333 : {
334 0 : GF_Matrix2D *mx = (GF_Matrix2D *)field->far_ptr;
335 0 : if (!gf_mx2d_is_identity(*mx) && !(!mx->m[0] && !mx->m[1] && !mx->m[3] && !mx->m[4])) {
336 0 : StatFixed(stat, mx->m[0], 1);
337 0 : StatFixed(stat, mx->m[1], 1);
338 0 : StatFixed(stat, mx->m[3], 1);
339 0 : StatFixed(stat, mx->m[4], 1);
340 0 : StatFixed(stat, mx->m[2], 0);
341 0 : StatFixed(stat, mx->m[5], 0);
342 : }
343 : }
344 : break;
345 438 : case SVG_Length_datatype:
346 : case SVG_Coordinate_datatype:
347 438 : StatFixed(stat, ((SVG_Number *)field->far_ptr)->value, 0);
348 : break;
349 : }
350 2744 : }
351 : #endif
352 :
353 : static void StatRemField(GF_SceneStatistics *stat, u32 fieldType, GF_FieldInfo *field)
354 : {
355 : u32 count = 1;
356 : if (field) count = ((GenMFField*)field->far_ptr)->count;
357 6 : switch (fieldType) {
358 0 : case GF_SG_VRML_MFFLOAT:
359 0 : stat->rem_float += count;
360 : break;
361 0 : case GF_SG_VRML_SFCOLOR:
362 0 : stat->rem_color += count;
363 : break;
364 0 : case GF_SG_VRML_MFVEC2F:
365 0 : stat->rem_2d += count;
366 : break;
367 0 : case GF_SG_VRML_MFVEC3F:
368 0 : stat->rem_3d += count;
369 : break;
370 : }
371 : }
372 :
373 :
374 2235 : Bool StatIsUSE(GF_StatManager *st, GF_Node *n)
375 : {
376 : u32 i;
377 : GF_Node *ptr;
378 2235 : if (!n || !gf_node_get_id(n) ) return 0;
379 932 : i=0;
380 125740 : while ((ptr = (GF_Node*)gf_list_enum(st->def_nodes, &i))) {
381 123918 : if (ptr == n) return 1;
382 : }
383 890 : gf_list_add(st->def_nodes, n);
384 890 : return 0;
385 : }
386 :
387 2763 : static GF_Err StatNodeGraph(GF_StatManager *st, GF_Node *n)
388 : {
389 : GF_Node *clone;
390 : GF_FieldInfo field;
391 : Bool no_cycle;
392 2763 : if (!n) return GF_OK;
393 :
394 2235 : no_cycle = gf_node_set_cyclic_traverse_flag(n, GF_TRUE);
395 2235 : StatNode(st->stats, n, StatIsUSE(st, n), 0, NULL);
396 :
397 2235 : if (!no_cycle) return GF_OK;
398 :
399 2235 : if (n->sgprivate->tag != TAG_ProtoNode) {
400 2211 : clone = gf_node_new(n->sgprivate->scenegraph, n->sgprivate->tag);
401 : } else {
402 : #ifndef GPAC_DISABLE_VRML
403 24 : clone = gf_sg_proto_create_node(n->sgprivate->scenegraph, ((GF_ProtoInstance *)n)->proto_interface, NULL);
404 : #else
405 : clone = NULL;
406 : #endif
407 : }
408 2235 : if (!clone) return GF_OK;
409 2235 : gf_node_register(clone, NULL);
410 :
411 : #ifndef GPAC_DISABLE_SVG
412 2235 : if ((n->sgprivate->tag>= GF_NODE_RANGE_FIRST_SVG) && (n->sgprivate->tag<= GF_NODE_RANGE_LAST_SVG)) {
413 900 : GF_ChildNodeItem *list = ((SVG_Element *)n)->children;
414 900 : GF_DOMAttribute *atts = ((GF_DOMNode*)n)->attributes;
415 4544 : while (atts) {
416 2744 : field.far_ptr = atts->data;
417 2744 : field.fieldType = atts->data_type;
418 2744 : field.fieldIndex = atts->tag;
419 2744 : field.name = NULL;
420 2744 : StatSVGAttribute(st->stats, &field);
421 :
422 2744 : atts = atts->next;
423 : }
424 1969 : while (list) {
425 1069 : StatNodeGraph(st, list->node);
426 1069 : list = list->next;
427 : }
428 : } else
429 : #endif
430 1335 : if (n->sgprivate->tag == TAG_DOMText) {
431 1175 : } else if (n->sgprivate->tag == TAG_DOMFullNode) {
432 : }
433 : #ifndef GPAC_DISABLE_VRML
434 1148 : else if (n->sgprivate->tag<= GF_NODE_RANGE_LAST_X3D) {
435 : GF_Node *child;
436 : GF_ChildNodeItem *list;
437 : u32 i, count;
438 : GF_FieldInfo clone_field;
439 :
440 1148 : count = gf_node_get_field_count(n);
441 :
442 9386 : for (i=0; i<count; i++) {
443 8238 : gf_node_get_field(n, i, &field);
444 8238 : if (field.eventType==GF_SG_EVENT_IN) continue;
445 6756 : if (field.eventType==GF_SG_EVENT_OUT) continue;
446 :
447 5534 : switch (field.fieldType) {
448 1038 : case GF_SG_VRML_SFNODE:
449 1038 : child = *((GF_Node **)field.far_ptr);
450 1038 : StatNodeGraph(st, child);
451 1038 : break;
452 186 : case GF_SG_VRML_MFNODE:
453 186 : list = *((GF_ChildNodeItem **)field.far_ptr);
454 936 : while (list) {
455 564 : StatNodeGraph(st, list->node);
456 564 : list = list->next;
457 : }
458 : break;
459 4310 : default:
460 4310 : gf_node_get_field(clone, i, &clone_field);
461 4310 : if (!gf_sg_vrml_field_equal(clone_field.far_ptr, field.far_ptr, field.fieldType)) {
462 1050 : StatField(st->stats, &field);
463 : }
464 : break;
465 : }
466 : }
467 : }
468 : #endif
469 :
470 2235 : gf_node_unregister(clone, NULL);
471 2235 : gf_node_set_cyclic_traverse_flag(n, GF_FALSE);
472 2235 : return GF_OK;
473 : }
474 :
475 : GF_EXPORT
476 238 : GF_Err gf_sm_stats_for_command(GF_StatManager *stat, GF_Command *com)
477 : {
478 : #ifdef GPAC_DISABLE_VRML
479 : return GF_NOT_SUPPORTED;
480 : #else
481 : GF_FieldInfo field;
482 : GF_Err e;
483 : GF_ChildNodeItem *list;
484 : u32 i;
485 : GF_CommandField *inf = NULL;
486 238 : if (gf_list_count(com->command_fields))
487 136 : inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
488 :
489 238 : if (!com || !stat) return GF_BAD_PARAM;
490 238 : switch (com->tag) {
491 18 : case GF_SG_SCENE_REPLACE:
492 18 : if (com->node) StatNodeGraph(stat, com->node);
493 : break;
494 30 : case GF_SG_NODE_REPLACE:
495 30 : if (inf && inf->new_node) StatNodeGraph(stat, inf->new_node);
496 : break;
497 12 : case GF_SG_FIELD_REPLACE:
498 12 : if (!inf) return GF_OK;
499 12 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
500 12 : if (e) return e;
501 :
502 12 : switch (field.fieldType) {
503 4 : case GF_SG_VRML_SFNODE:
504 4 : if (inf->new_node) StatNodeGraph(stat, inf->new_node);
505 : break;
506 : case GF_SG_VRML_MFNODE:
507 : if (inf) {
508 2 : list = * ((GF_ChildNodeItem**) inf->field_ptr);
509 6 : while (list) {
510 2 : StatNodeGraph(stat, list->node);
511 2 : list = list->next;
512 : }
513 : }
514 : break;
515 : default:
516 : if (inf) {
517 6 : field.far_ptr = inf->field_ptr;
518 6 : StatField(stat->stats, &field);
519 : }
520 : break;
521 : }
522 : break;
523 18 : case GF_SG_INDEXED_REPLACE:
524 18 : if (!inf) return GF_OK;
525 18 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
526 18 : if (e) return e;
527 :
528 18 : if (field.fieldType == GF_SG_VRML_MFNODE) {
529 12 : StatNodeGraph(stat, inf->new_node);
530 : } else {
531 6 : field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
532 6 : field.far_ptr = inf->field_ptr;
533 6 : StatSingleField(stat->stats, &field);
534 : }
535 : break;
536 18 : case GF_SG_NODE_DELETE:
537 : case GF_SG_NODE_DELETE_EX:
538 : case GF_SG_GLOBAL_QUANTIZER:
539 18 : if (com->node) StatNode(stat->stats, com->node, 0, 1, NULL);
540 : break;
541 6 : case GF_SG_INDEXED_DELETE:
542 6 : if (!inf) return GF_OK;
543 6 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
544 6 : if (e) return e;
545 :
546 : /*then we need special handling in case of a node*/
547 6 : if (gf_sg_vrml_get_sf_type(field.fieldType) == GF_SG_VRML_SFNODE) {
548 0 : GF_Node *n = gf_node_list_get_child( * (GF_ChildNodeItem **) field.far_ptr, inf->pos);
549 0 : if (n) StatNode(stat->stats, n, 0, 1, NULL);
550 : } else {
551 6 : StatRemField(stat->stats, inf->fieldType, NULL);
552 : }
553 : break;
554 30 : case GF_SG_NODE_INSERT:
555 30 : if (inf && inf->new_node) StatNodeGraph(stat, inf->new_node);
556 : break;
557 8 : case GF_SG_INDEXED_INSERT:
558 8 : if (!inf) return GF_OK;
559 8 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
560 8 : if (e) return e;
561 :
562 : /*rescale the MFField and parse the SFField*/
563 8 : if (field.fieldType != GF_SG_VRML_MFNODE) {
564 6 : field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
565 6 : field.far_ptr = inf->field_ptr;
566 6 : StatSingleField(stat->stats, &field);
567 : } else {
568 2 : if (inf->new_node) StatNodeGraph(stat, inf->new_node);
569 : }
570 : break;
571 : case GF_SG_ROUTE_REPLACE:
572 : case GF_SG_ROUTE_DELETE:
573 : case GF_SG_ROUTE_INSERT:
574 : return GF_OK;
575 12 : case GF_SG_XREPLACE:
576 12 : if (!inf) return GF_OK;
577 12 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
578 12 : if (e) return e;
579 :
580 : /*rescale the MFField and parse the SFField*/
581 12 : if (field.fieldType != GF_SG_VRML_MFNODE) {
582 6 : field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
583 6 : field.far_ptr = inf->field_ptr;
584 6 : StatSingleField(stat->stats, &field);
585 : } else {
586 6 : if (inf->new_node) StatNodeGraph(stat, inf->new_node);
587 : }
588 :
589 : break;
590 : case GF_SG_MULTIPLE_REPLACE:
591 : case GF_SG_MULTIPLE_INDEXED_REPLACE:
592 38 : for (i=0; i<gf_list_count(com->command_fields); i++) {
593 38 : inf = (GF_CommandField*)gf_list_get(com->command_fields, i);
594 38 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
595 38 : if (e) return e;
596 :
597 : /*rescale the MFField and parse the SFField*/
598 38 : if (field.fieldType != GF_SG_VRML_MFNODE) {
599 36 : field.fieldType = gf_sg_vrml_get_sf_type(field.fieldType);
600 36 : field.far_ptr = inf->field_ptr;
601 36 : StatSingleField(stat->stats, &field);
602 : } else {
603 2 : if (inf->new_node) StatNodeGraph(stat, inf->new_node);
604 : }
605 : }
606 : break;
607 : case GF_SG_PROTO_INSERT:
608 : case GF_SG_PROTO_DELETE:
609 : case GF_SG_PROTO_DELETE_ALL:
610 : return GF_OK;
611 :
612 0 : default:
613 0 : return GF_BAD_PARAM;
614 : }
615 : return GF_OK;
616 : #endif
617 : }
618 :
619 45 : static GF_Err gf_sm_stat_au(GF_List *commandList, GF_StatManager *st)
620 : {
621 : u32 i, count;
622 45 : count = gf_list_count(commandList);
623 164 : for (i=0; i<count; i++) {
624 119 : GF_Command *com = (GF_Command *)gf_list_get(commandList, i);
625 119 : gf_sm_stats_for_command(st, com);
626 : }
627 45 : return GF_OK;
628 : }
629 :
630 : GF_EXPORT
631 21 : GF_Err gf_sm_stats_for_scene(GF_StatManager *stat, GF_SceneManager *sm)
632 : {
633 : u32 i, j;
634 : GF_StreamContext *sc;
635 : GF_Err e;
636 :
637 21 : if (gf_list_count(sm->streams)) {
638 3 : i=0;
639 16 : while ((sc = (GF_StreamContext*)gf_list_enum(sm->streams, &i))) {
640 : GF_AUContext *au;
641 10 : if (sc->streamType != GF_STREAM_SCENE) continue;
642 :
643 3 : if (!stat->stats->base_layer)
644 3 : stat->stats->base_layer = sc;
645 :
646 3 : j=0;
647 51 : while ((au = (GF_AUContext*)gf_list_enum(sc->AUs, &j))) {
648 45 : e = gf_sm_stat_au(au->commands, stat);
649 45 : if (e) return e;
650 : }
651 : }
652 : } else { /* No scene stream: e.g. SVG */
653 18 : if (sm->scene_graph) gf_sm_stats_for_graph(stat, sm->scene_graph);
654 : }
655 : return GF_OK;
656 : }
657 :
658 : GF_EXPORT
659 18 : GF_Err gf_sm_stats_for_graph(GF_StatManager *stat, GF_SceneGraph *sg)
660 : {
661 18 : if (!stat || !sg) return GF_BAD_PARAM;
662 18 : return StatNodeGraph(stat, sg->RootNode);
663 : }
664 :
665 : /*creates new stat handler*/
666 : GF_EXPORT
667 24 : GF_StatManager *gf_sm_stats_new()
668 : {
669 24 : GF_StatManager *sm = (GF_StatManager *)gf_malloc(sizeof(GF_StatManager));
670 24 : sm->def_nodes = gf_list_new();
671 24 : sm->stats = NewSceneStats();
672 24 : return sm;
673 :
674 : }
675 : /*deletes stat object returned by one of the above functions*/
676 : GF_EXPORT
677 24 : void gf_sm_stats_del(GF_StatManager *stat)
678 : {
679 24 : gf_list_del(stat->def_nodes);
680 24 : DeleteStatisitics(stat->stats);
681 24 : gf_free(stat);
682 24 : }
683 :
684 : GF_EXPORT
685 66 : const GF_SceneStatistics *gf_sm_stats_get(GF_StatManager *stat)
686 : {
687 66 : return stat->stats;
688 : }
689 :
690 : GF_EXPORT
691 45 : void gf_sm_stats_reset(GF_StatManager *stat)
692 : {
693 45 : if (!stat) return;
694 45 : ResetStatisitics(stat->stats);
695 : }
696 :
697 : #endif /*GPAC_DISABLE_SCENE_STATS*/
698 :
|