LCOV - code coverage report
Current view: top level - scene_manager - scene_stats.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 337 360 93.6 %
Date: 2021-04-29 23:48:07 Functions: 20 20 100.0 %

          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             : 

Generated by: LCOV version 1.13