1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2004-2012
6 * All rights reserved
7 *
8 * This file is part of GPAC / MPEG4 Scene Graph Generator 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 <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #undef _DEBUG
31 #undef DEBUG
32
33 #include <gpac/list.h>
34
35
36 #include <time.h>
37
38
39 #define COPYRIGHT_SCENE "/*\n * GPAC - Multimedia Framework C SDK\n *\n * Authors: Jean Le Feuvre\n * Copyright (c) Telecom ParisTech 2000-2012\n * All rights reserved\n *\n * This file is part of GPAC / Scene Graph sub-project\n *\n * GPAC is free software; you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation; either version 2, or (at your option)\n * any later version.\n *\n * GPAC is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details. \n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; see the file COPYING. If not, write to\n * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n"
40 #define COPYRIGHT_BIFS "/*\n * GPAC - Multimedia Framework C SDK\n *\n * Authors: Jean Le Feuvre\n * Copyright (c) Telecom ParisTech 2000-2012\n * All rights reserved\n *\n * This file is part of GPAC / BIFS codec sub-project\n *\n * GPAC is free software; you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation; either version 2, or (at your option)\n * any later version.\n *\n * GPAC is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details. \n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; see the file COPYING. If not, write to\n * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n"
41
42 static char *CurrentLine;
43
PrintUsage()44 void PrintUsage()
45 {
46 printf("MPEG4Gen [-p file] [template_file_v1 (template_file_v2 ...) ]\n"
47 "\nGPAC MPEG4 Scene Graph generator. Usage:\n"
48 "-p: listing file of nodes to exclude from tables\n"
49 "Template files MUST be fed in order\n"
50 "\n"
51 "Generated Files are directly updated in the GPAC distribution - do NOT try to change this\n\n"
52 "Written by Jean Le Feuvre - Copyright (c) Telecom ParisTech 2000-2012\n"
53 );
54 }
55
56 //a node field
57 typedef struct
58 {
59 char type[50];
60 //SFxxx, MFxxx
61 char familly[50];
62 //name
63 char name[1000];
64 //default value
65 char def[100];
66 //bounds
67 u32 hasBounds;
68 char b_min[20];
69 char b_max[20];
70 //Quant
71 u32 hasQuant;
72 char quant_type[50];
73 char qt13_bits[50];
74 //Anim
75 u32 hasAnim;
76 u32 AnimType;
77
78 } BField;
79
80 //NDTs
81
82 //a BIFS node
83 typedef struct
84 {
85 char name[1000];
86 //NDT info. NDT are created in alphabetical order
87 GF_List *NDT;
88 //0: normal, 1: special
89 u32 codingType;
90 u32 version;
91
92 GF_List *Fields;
93
94 //coding types
95 u8 hasDef, hasIn, hasOut, hasDyn;
96 u8 hasAQInfo;
97
98 u8 hasDefault;
99
100 u8 skip_impl;
101
102 char Child_NDT_Name[1000];
103 } BNode;
104
105
skip_sep(char * sep)106 void skip_sep(char *sep)
107 {
108 //skip separaors
109 while (*CurrentLine && strchr(sep, *CurrentLine)) {
110 CurrentLine = CurrentLine + 1;
111 //end of line - no token
112 if (*CurrentLine == '\n') return;
113 }
114 }
115
116 //note that we increment the line no matter what
GetNextToken(char * token,char * sep)117 u32 GetNextToken(char *token, char *sep)
118 {
119 u32 i , j = 0;
120
121 strcpy(token, "");
122
123 //skip separaors
124 while (*CurrentLine && strchr(sep, *CurrentLine)) {
125 CurrentLine = CurrentLine + 1;
126 j ++;
127 //end of line - no token
128 if (*CurrentLine == '\n') return 0;
129 }
130
131 //copy token untill next blank
132 i=0;
133 while (1) {
134 //bad line
135 if (! *CurrentLine) {
136 token[i] = 0;
137 return 0;
138 }
139 //end of token or end of line
140 if (strchr(sep, *CurrentLine) || (*CurrentLine == '\n') ) {
141 token[i] = 0;
142 CurrentLine = CurrentLine + 1;
143 return i;
144 } else {
145 token[i] = *CurrentLine;
146 }
147 CurrentLine = CurrentLine + 1;
148 i++;
149 j++;
150 }
151 return 1;
152 }
153
154
155 char szFixedVal[5000];
GetFixedPrintout(char * val)156 char *GetFixedPrintout(char *val)
157 {
158 if (!strcmp(val, "FIX_MIN") || !strcmp(val, "FIX_MAX")) return val;
159 /*composite texture...*/
160 if (!strcmp(val, "65535")) return "FIX_MAX /*WARNING: modified to allow 16.16 fixed point version!!*/";
161 sprintf(szFixedVal, "FLT2FIX(%s)", val);
162 return szFixedVal;
163 }
164
BlankField()165 BField *BlankField()
166 {
167 BField *n = gf_malloc(sizeof(BField));
168 memset(n, 0, sizeof(BField));
169 return n;
170 }
171
172
BlankNode()173 BNode *BlankNode()
174 {
175 BNode *n = gf_malloc(sizeof(BNode));
176 memset(n, 0, sizeof(BNode));
177 n->NDT = gf_list_new();
178 n->Fields = gf_list_new();
179 return n;
180 }
181
IsNDT(GF_List * NDTs,char * famName)182 u8 IsNDT(GF_List *NDTs, char *famName)
183 {
184 u32 i;
185 for (i=0; i<gf_list_count(NDTs); i++) {
186 char *ndtName = gf_list_get(NDTs, i);
187 //remove SF / MF as we don't need that
188 if (!strcmp(ndtName+2, famName+2)) return 1;
189 }
190 return 0;
191 }
192
CheckInTable(char * token,GF_List * NDTs)193 void CheckInTable(char *token, GF_List *NDTs)
194 {
195 u32 i;
196 char *p;
197 for (i=0; i<gf_list_count(NDTs); i++) {
198 p = gf_list_get(NDTs, i);
199 if (!strcmp(p, token)) return;
200 }
201 p = gf_malloc(strlen(token)+1);
202 strcpy(p, token);
203 gf_list_add(NDTs, p);
204 }
205
206 /*type: 0: header, 1: source*/
BeginFile(char * name,u32 type)207 FILE *BeginFile(char *name, u32 type)
208 {
209 FILE *f;
210 char *cprt = COPYRIGHT_SCENE;
211 char sPath[GF_MAX_PATH];
212
213 if (!type) {
214 if (!strcmp(name, "NDT")) {
215 sprintf(sPath, "..%c..%c..%cinclude%cgpac%cinternal%cbifs_tables.h", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
216 cprt = COPYRIGHT_BIFS;
217 }
218 /*nodes_mpeg4.h is exported*/
219 else {
220 sprintf(sPath, "..%c..%c..%cinclude%cgpac%cnodes_mpeg4.h", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
221 }
222 } else {
223 if (!stricmp(name, "NDT")) {
224 sprintf(sPath, "..%c..%c..%csrc%cbifs%cbifs_node_tables.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
225 cprt = COPYRIGHT_BIFS;
226 } else {
227 sprintf(sPath, "..%c..%c..%csrc%cscenegraph%c%s.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, name);
228 }
229 }
230
231 f = gf_fopen(sPath, "wt");
232 fprintf(f, "%s\n", cprt);
233
234
235
236 {
237 time_t rawtime;
238 time(&rawtime);
239 fprintf(f, "\n/*\n\tDO NOT MOFIFY - File generated on GMT %s\n\tBY MPEG4Gen for GPAC Version %s\n*/\n\n", asctime(gmtime(&rawtime)), GPAC_VERSION);
240 }
241
242 if (!type) {
243 fprintf(f, "#ifndef _%s_H\n", name);
244 fprintf(f, "#define _%s_H\n\n", name);
245 if (!strcmp(name, "nodes_mpeg4")) {
246 fprintf(f, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n");
247 }
248 }
249 return f;
250 }
251
EndFile(FILE * f,char * name,u32 type)252 void EndFile(FILE *f, char *name, u32 type)
253 {
254 if (!type) {
255 if (!strcmp(name, "nodes_mpeg4")) {
256 fprintf(f, "#ifdef __cplusplus\n}\n#endif\n\n");
257 }
258 fprintf(f, "\n\n#endif\t\t/*_%s_H*/\n\n", name);
259 }
260 gf_fclose(f);
261 }
262
TranslateToken(char * token)263 void TranslateToken(char *token)
264 {
265 if (!strcmp(token, "+I") || !strcmp(token, "I")) {
266 strcpy(token, "FIX_MAX");
267 }
268 else if (!strcmp(token, "-I")) {
269 strcpy(token, "FIX_MIN");
270 }
271 }
272
273
274
WriteNodesFile(GF_List * BNodes,GF_List * NDTs,u32 NumVersions)275 void WriteNodesFile(GF_List *BNodes, GF_List *NDTs, u32 NumVersions)
276 {
277 FILE *f;
278 u32 i, j;
279 BNode *n;
280 BField *bf;
281 Bool hasViewport;
282
283 f = BeginFile("nodes_mpeg4", 0);
284
285 fprintf(f, "#include <gpac/scenegraph_vrml.h>\n\n");
286 fprintf(f, "#ifndef GPAC_DISABLE_VRML\n\n");
287
288
289 //write all tags
290 fprintf(f, "\n\nenum {\n");
291
292 for (i=0; i<gf_list_count(BNodes); i++) {
293 n = gf_list_get(BNodes, i);
294 if (i)
295 fprintf(f, ",\n\tTAG_MPEG4_%s", n->name);
296 else
297 fprintf(f, "\tTAG_MPEG4_%s = GF_NODE_RANGE_FIRST_MPEG4", n->name);
298 }
299 fprintf(f, ",\n\tTAG_LastImplementedMPEG4\n};\n\n");
300
301 for (i=0; i<gf_list_count(BNodes); i++) {
302 n = gf_list_get(BNodes, i);
303 if (n->skip_impl) continue;
304
305 fprintf(f, "typedef struct _tag%s\n{\n", n->name);
306 fprintf(f, "\tBASE_NODE\n");
307
308 /*write children field*/
309 for (j=0; j<gf_list_count(n->Fields); j++) {
310 bf = gf_list_get(n->Fields, j);
311 if (!stricmp(bf->name, "addChildren") || !strcmp(bf->name, "removeChildren")) continue;
312 if (!strcmp(bf->name, "children") && stricmp(n->name, "audioBuffer")) {
313 fprintf(f, "\tVRML_CHILDREN\n");
314 break;
315 }
316 }
317 for (j=0; j<gf_list_count(n->Fields); j++) {
318 bf = gf_list_get(n->Fields, j);
319
320 if (!strcmp(bf->name, "addChildren") || !strcmp(bf->name, "removeChildren")) continue;
321 if (!strcmp(bf->name, "children") && stricmp(n->name, "audioBuffer")) continue;
322
323 //write remaining fields
324 //eventIn fields are handled as pointer to functions, called by the route manager
325 if (!strcmp(bf->type, "eventIn")) {
326 if (strstr(bf->familly, "Node")) {
327 fprintf(f, "\tGF_Node *%s;\t/*eventIn*/\n",bf->name);
328 } else {
329 fprintf(f, "\t%s %s;\t/*eventIn*/\n", bf->familly, bf->name);
330 }
331 fprintf(f, "\tvoid (*on_%s)(GF_Node *pThis, struct _route *route);\t/*eventInHandler*/\n", bf->name);
332 } else if (!strcmp(bf->type, "eventOut")) {
333 //eventOut fields are handled as an opaque stack pointing to the route manager
334 //this will be refined once the route is in place
335 //we will likely need a function such as:
336 // void SignalRoute(route_stack, node, par)
337 fprintf(f, "\t%s %s;\t/*eventOut*/\n", bf->familly, bf->name);
338 } else if (strstr(bf->familly, "Node")) {
339 //this is a POINTER to a node
340 if (strstr(bf->familly, "SF")) {
341 fprintf(f, "\tGF_Node *%s;\t/*%s*/\n", bf->name, bf->type);
342 } else {
343 //this is a POINTER to a chain
344 fprintf(f, "\tGF_ChildNodeItem *%s;\t/*%s*/\n", bf->name, bf->type);
345 }
346 } else {
347 fprintf(f, "\t%s %s;\t/*%s*/\n", bf->familly, bf->name, bf->type);
348 }
349 }
350 if (!strcmp(n->name, "CacheTexture")) {
351 fprintf(f, "\t/*GPAC private*/\n");
352 fprintf(f, "\tu8 *data;\n");
353 fprintf(f, "\tu32 data_len;\n");
354 }
355 if (!strcmp(n->name, "BitWrapper")) {
356 fprintf(f, "\t/*GPAC private*/\n");
357 fprintf(f, "\tu32 buffer_len;\n");
358 }
359 fprintf(f, "} M_%s;\n\n\n", n->name);
360 }
361
362
363 hasViewport = 0;
364 //all NDTs are defined in v1
365 fprintf(f, "/*NodeDataType tags*/\nenum {\n");
366 for (i=0; i<gf_list_count(NDTs); i++) {
367 char *NDTName = gf_list_get(NDTs, i);
368 if (!i) {
369 fprintf(f, "\tNDT_%s = 1", NDTName);
370 } else {
371 fprintf(f, ",\n\tNDT_%s", NDTName);
372 }
373
374 if (strcmp(NDTName, "SFViewportNode")) hasViewport = 1;
375 }
376 //template fix: some node use NDT_SFViewportNode but the table is empty-> not generated
377 if (!hasViewport) fprintf(f, ",\n\tNDT_SFViewportNode");
378 fprintf(f, "\n};\n\n");
379
380
381 fprintf(f, "/*All BIFS versions handled*/\n");
382 fprintf(f, "#define GF_BIFS_NUM_VERSION\t\t%d\n\n", NumVersions);
383 fprintf(f, "enum {\n");
384 for (i=0; i<NumVersions; i++) {
385 if (!i) {
386 fprintf(f, "\tGF_BIFS_V1 = 1,\n");
387 } else {
388 fprintf(f, "\tGF_BIFS_V%d,\n", i+1);
389 }
390 }
391 fprintf(f, "\tGF_BIFS_LAST_VERSION = GF_BIFS_V%d\n};\n\n", i);
392 fprintf(f, "\n\n");
393 fprintf(f, "#endif /*GPAC_DISABLE_VRML*/\n\n");
394
395 EndFile(f, "nodes_mpeg4", 0);
396
397 }
398
399
IsNodeInTable(BNode * node,char * NDTName)400 u32 IsNodeInTable(BNode *node, char *NDTName)
401 {
402 u32 i;
403
404 for (i=0; i<gf_list_count(node->NDT); i++) {
405 char *ndt = gf_list_get(node->NDT, i);
406 if (!strcmp(ndt, NDTName)) return 1;
407 }
408 return 0;
409 }
410
GetBitsCount(u32 MaxVal)411 u32 GetBitsCount(u32 MaxVal)
412 {
413 u32 k=0;
414
415 while ((s32) MaxVal > ((1<<k)-1) ) k+=1;
416 return k;
417 }
418
GetNDTCount(char * NDTName,GF_List * BNodes,u32 Version)419 u32 GetNDTCount(char *NDTName, GF_List *BNodes, u32 Version)
420 {
421 u32 i, nodeCount;
422
423 //V1 begins at 0
424 if (Version == 1) {
425 nodeCount = 0;
426 }
427 //V2 at 2 (0 reserved + 1 proto)
428 else if (Version == 2) {
429 nodeCount = 2;
430 }
431 //other at 1 (0 reserved, no proto)
432 else {
433 nodeCount = 1;
434 }
435 for (i=0; i<gf_list_count(BNodes); i++) {
436 BNode *n = gf_list_get(BNodes, i);
437 if (n->version != Version) continue;
438 if (!IsNodeInTable(n, NDTName)) continue;
439 nodeCount++;
440 }
441 return nodeCount;
442
443 }
444
WriteNDT_H(FILE * f,GF_List * BNodes,GF_List * NDTs,u32 Version)445 void WriteNDT_H(FILE *f, GF_List *BNodes, GF_List *NDTs, u32 Version)
446 {
447 u32 i, j, first, count;
448 BNode *n;
449
450
451 fprintf(f, "\n\n/* NDT BIFS Version %d */\n\n", Version);
452
453 //for all NDTs
454 for (i=0; i<gf_list_count(NDTs); i++) {
455 char *NDTName = gf_list_get(NDTs, i);
456 count = GetNDTCount(NDTName, BNodes, Version);
457 if (Version == 2) {
458 count -= 2;
459 } else if (Version > 2) {
460 count -= 1;
461 }
462 if (!count) continue;
463
464 //numBits
465 fprintf(f, "#define %s_V%d_NUMBITS\t\t%d\n", NDTName, Version, GetBitsCount(count + ( (Version == 2) ? 1 : 0) ) );
466 fprintf(f, "#define %s_V%d_Count\t%d\n\n", NDTName, Version, count);
467
468 fprintf(f, "static const u32 %s_V%d_TypeToTag[%d] = {\n", NDTName, Version, count);
469 first = 1;
470 //browse each node.
471 for (j=0; j<gf_list_count(BNodes); j++) {
472 n = gf_list_get(BNodes, j);
473 if (n->version != Version) continue;
474 if (!IsNodeInTable(n, NDTName)) continue;
475
476 if (first) {
477 fprintf(f, " TAG_MPEG4_%s", n->name);
478 first = 0;
479 } else {
480 fprintf(f, ", TAG_MPEG4_%s", n->name);
481 }
482 }
483 fprintf(f, "\n};\n\n");
484
485 }
486
487 fprintf(f, "\nu32 NDT_V%d_GetNumBits(u32 NDT_Tag);\n", Version);
488 fprintf(f, "u32 NDT_V%d_GetNodeTag(u32 Context_NDT_Tag, u32 NodeType);\n", Version);
489 fprintf(f, "u32 NDT_V%d_GetNodeType(u32 NDT_Tag, u32 NodeTag);\n", Version);
490
491 fprintf(f, "\n\n");
492 }
493
494 //write the NDTs functions for v1 nodes
495 //all our internal handling is in TAG_MPEG4_#nodename because we need an homogeneous
496 //namespace for all nodes (v1, v2, v3 and v4)
497 //the NDT functions will perform the translation from the NDT value to the absolute
498 //TAG of the node
WriteNDT_Dec(FILE * f,GF_List * BNodes,GF_List * NDTs,u32 Version)499 void WriteNDT_Dec(FILE *f, GF_List *BNodes, GF_List *NDTs, u32 Version)
500 {
501 char *NDTName;
502 u32 i, count;
503
504 //NodeTag complete translation
505 fprintf(f, "\n\n\nu32 NDT_V%d_GetNodeTag(u32 Context_NDT_Tag, u32 NodeType)\n{\n\tif (!NodeType) return 0;\n", Version);
506
507 //handle version
508 fprintf(f, "\t/* adjust according to the table version */\n");
509 if (Version == 2) {
510 fprintf(f, "\t/* v2: 0 reserved for extensions, 1 reserved for protos */\n");
511 fprintf(f, "\tif (NodeType == 1) return 0;\n");
512 fprintf(f, "\tNodeType -= 2;\n");
513 } else {
514 fprintf(f, "\t/* v%d: 0 reserved for extensions */\n", Version);
515 fprintf(f, "\tNodeType -= 1;\n");
516 }
517
518 fprintf(f, "\tswitch (Context_NDT_Tag) {\n");
519
520 for (i=0; i<gf_list_count(NDTs); i++) {
521 NDTName = gf_list_get(NDTs, i);
522
523 count = GetNDTCount(NDTName, BNodes, Version);
524 if (Version == 2) {
525 count -= 2;
526 } else if (Version > 2) {
527 count -= 1;
528 }
529 if (!count) continue;
530
531 fprintf(f, "\tcase NDT_%s:\n\t\tif (NodeType >= %s_V%d_Count) return 0;\n", NDTName, NDTName, Version);
532 fprintf(f, "\t\treturn %s_V%d_TypeToTag[NodeType];\n", NDTName, Version);
533 }
534 fprintf(f, "\tdefault:\n\t\treturn 0;\n\t}\n}");
535
536 //NDT codec bits
537 fprintf(f, "\n\n\nu32 NDT_V%d_GetNumBits(u32 NDT_Tag)\n{\n\tswitch (NDT_Tag) {\n", Version);
538
539 for (i=0; i<gf_list_count(NDTs); i++) {
540 NDTName = gf_list_get(NDTs, i);
541
542 count = GetNDTCount(NDTName, BNodes, Version);
543 if (Version == 2) {
544 count -= 2;
545 } else if (Version > 2) {
546 count -= 1;
547 }
548 if (!count) continue;
549
550 fprintf(f, "\tcase NDT_%s:\n\t\treturn %s_V%d_NUMBITS;\n", NDTName, NDTName, Version);
551 }
552 /*all tables have 1 node in v2 for proto coding*/
553 fprintf(f, "\tdefault:\n\t\treturn %d;\n\t}\n}\n\n", (Version==2) ? 1 : 0);
554 }
555
556
WriteNDT_Enc(FILE * f,GF_List * BNodes,GF_List * NDTs,u32 Version)557 void WriteNDT_Enc(FILE *f, GF_List *BNodes, GF_List *NDTs, u32 Version)
558 {
559 u32 i, count;
560
561 fprintf(f, "u32 NDT_V%d_GetNodeType(u32 NDT_Tag, u32 NodeTag)\n{\n\tif(!NDT_Tag || !NodeTag) return 0;\n\tswitch(NDT_Tag) {\n", Version);
562 for (i=0; i<gf_list_count(NDTs); i++) {
563 char *NDTName = gf_list_get(NDTs, i);
564 count = GetNDTCount(NDTName, BNodes, Version);
565 if (Version == 2) {
566 count -= 2;
567 } else if (Version > 2) {
568 count -= 1;
569 }
570 if (!count) continue;
571 fprintf(f, "\tcase NDT_%s:\n\t\treturn ALL_GetNodeType(%s_V%d_TypeToTag, %s_V%d_Count, NodeTag, GF_BIFS_V%d);\n", NDTName, NDTName, Version, NDTName, Version, Version);
572 }
573 fprintf(f, "\tdefault:\n\t\treturn 0;\n\t}\n}\n\n");
574 }
575
576
577
WriteNodeFields(FILE * f,BNode * n)578 void WriteNodeFields(FILE *f, BNode *n)
579 {
580 u32 i, first;
581 BField *bf;
582 u32 NbDef, NbIn, NbOut, NbDyn, hasAQ;
583
584 NbDef = NbIn = NbOut = NbDyn = hasAQ = 0;
585 for (i=0; i<gf_list_count(n->Fields); i++) {
586 bf = gf_list_get(n->Fields, i);
587 if (!strcmp(bf->type, "field") || !strcmp(bf->type, "exposedField")) {
588 NbDef += 1;
589 }
590 if (!strcmp(bf->type, "eventIn") || !strcmp(bf->type, "exposedField")) {
591 NbIn += 1;
592 //check for anim
593 if (bf->hasAnim) NbDyn += 1;
594 }
595 if (!strcmp(bf->type, "eventOut") || !strcmp(bf->type, "exposedField")) {
596 NbOut += 1;
597 }
598 if (bf->hasAnim || bf->hasQuant) hasAQ = 1;
599 }
600
601 n->hasAQInfo = hasAQ;
602
603 //write the def2all table
604 if (NbDef) {
605 first = 1;
606 fprintf(f, "static const u16 %s_Def2All[] = { ", n->name);
607 for (i=0; i<gf_list_count(n->Fields); i++) {
608 bf = gf_list_get(n->Fields, i);
609 if (strcmp(bf->type, "field") && strcmp(bf->type, "exposedField")) continue;
610 if (first) {
611 fprintf(f, "%d", i);
612 first = 0;
613 } else {
614 fprintf(f, ", %d", i);
615 }
616 }
617 fprintf(f, "};\n");
618 }
619 //write the in2all table
620 if (NbIn) {
621 first = 1;
622 fprintf(f, "static const u16 %s_In2All[] = { ", n->name);
623 for (i=0; i<gf_list_count(n->Fields); i++) {
624 bf = gf_list_get(n->Fields, i);
625 if (strcmp(bf->type, "eventIn") && strcmp(bf->type, "exposedField")) continue;
626 if (first) {
627 fprintf(f, "%d", i);
628 first = 0;
629 } else {
630 fprintf(f, ", %d", i);
631 }
632 }
633 fprintf(f, "};\n");
634 }
635 //write the out2all table
636 if (NbOut) {
637 first = 1;
638 fprintf(f, "static const u16 %s_Out2All[] = { ", n->name);
639 for (i=0; i<gf_list_count(n->Fields); i++) {
640 bf = gf_list_get(n->Fields, i);
641 if (strcmp(bf->type, "eventOut") && strcmp(bf->type, "exposedField")) continue;
642 if (first) {
643 fprintf(f, "%d", i);
644 first = 0;
645 } else {
646 fprintf(f, ", %d", i);
647 }
648 }
649 fprintf(f, "};\n");
650 }
651 //then write the dyn2all table
652 if (NbDyn) {
653 first = 1;
654 fprintf(f, "static const u16 %s_Dyn2All[] = { ", n->name);
655 for (i=0; i<gf_list_count(n->Fields); i++) {
656 bf = gf_list_get(n->Fields, i);
657 if (strcmp(bf->type, "eventIn") && strcmp(bf->type, "exposedField")) continue;
658 if (!bf->hasAnim) continue;
659 if (first) {
660 fprintf(f, "%d", i);
661 first = 0;
662 } else {
663 fprintf(f, ", %d", i);
664 }
665 }
666 fprintf(f, "};\n");
667 }
668
669 n->hasDef = NbDef;
670 n->hasDyn = NbDyn;
671 n->hasIn = NbIn;
672 n->hasOut = NbOut;
673
674
675 fprintf(f, "\nstatic u32 %s_get_field_count(GF_Node *node, u8 IndexMode)\n{\n", n->name);
676 fprintf(f, "\tswitch(IndexMode) {\n");
677
678 fprintf(f, "\tcase GF_SG_FIELD_CODING_IN: return %d;\n", NbIn);
679 fprintf(f, "\tcase GF_SG_FIELD_CODING_DEF: return %d;\n", NbDef);
680 fprintf(f, "\tcase GF_SG_FIELD_CODING_OUT: return %d;\n", NbOut);
681 fprintf(f, "\tcase GF_SG_FIELD_CODING_DYN: return %d;\n", NbDyn);
682 fprintf(f, "\tdefault:\n");
683 fprintf(f, "\t\treturn %d;\n", gf_list_count(n->Fields));
684 fprintf(f, "\t}");
685
686 fprintf(f, "\n}\n");
687
688 fprintf(f, "\nstatic GF_Err %s_get_field_index(GF_Node *n, u32 inField, u8 IndexMode, u32 *allField)\n{\n", n->name);
689 fprintf(f, "\tswitch(IndexMode) {\n");
690
691 if (NbIn) {
692 fprintf(f, "\tcase GF_SG_FIELD_CODING_IN:\n");
693 fprintf(f, "\t\t*allField = %s_In2All[inField];\n\t\treturn GF_OK;\n", n->name);
694 }
695 if (NbDef) {
696 fprintf(f, "\tcase GF_SG_FIELD_CODING_DEF:\n");
697 fprintf(f, "\t\t*allField = %s_Def2All[inField];\n\t\treturn GF_OK;\n", n->name);
698 }
699 if (NbOut) {
700 fprintf(f, "\tcase GF_SG_FIELD_CODING_OUT:\n");
701 fprintf(f, "\t\t*allField = %s_Out2All[inField];\n\t\treturn GF_OK;\n", n->name);
702 }
703 if (NbDyn) {
704 fprintf(f, "\tcase GF_SG_FIELD_CODING_DYN:\n");
705 fprintf(f, "\t\t*allField = %s_Dyn2All[inField];\n\t\treturn GF_OK;\n", n->name);
706 }
707
708 fprintf(f, "\tdefault:\n");
709 fprintf(f, "\t\treturn GF_BAD_PARAM;\n");
710 fprintf(f, "\t}");
711
712 fprintf(f, "\n}\n");
713
714
715 fprintf(f, "static GF_Err %s_get_field(GF_Node *node, GF_FieldInfo *info)\n{\n\tswitch (info->fieldIndex) {\n", n->name);
716 for (i=0; i<gf_list_count(n->Fields); i++) {
717 bf = gf_list_get(n->Fields, i);
718
719 fprintf(f, "\tcase %d:\n", i);
720
721 fprintf(f, "\t\tinfo->name = \"%s\";\n", (bf->name[0]=='_') ? bf->name+1 : bf->name);
722
723 //skip all eventIn
724 if (!strcmp(bf->type, "eventIn")) {
725 fprintf(f, "\t\tinfo->eventType = GF_SG_EVENT_IN;\n");
726 fprintf(f, "\t\tinfo->on_event_in = ((M_%s *)node)->on_%s;\n", n->name, bf->name);
727 }
728 else if (!strcmp(bf->type, "eventOut")) {
729 fprintf(f, "\t\tinfo->eventType = GF_SG_EVENT_OUT;\n");
730 }
731 else if (!strcmp(bf->type, "field")) {
732 fprintf(f, "\t\tinfo->eventType = GF_SG_EVENT_FIELD;\n");
733 }
734 else {
735 fprintf(f, "\t\tinfo->eventType = GF_SG_EVENT_EXPOSED_FIELD;\n");
736 }
737
738 if (strstr(bf->familly, "Node")) {
739 if (strstr(bf->familly, "MF")) {
740 fprintf(f, "\t\tinfo->fieldType = GF_SG_VRML_MFNODE;\n");
741 } else {
742 fprintf(f, "\t\tinfo->fieldType = GF_SG_VRML_SFNODE;\n");
743 }
744 //always remove the SF or MF, as all NDTs are SFXXX
745 fprintf(f, "\t\tinfo->NDTtype = NDT_SF%s;\n", bf->familly+2);
746 fprintf(f, "\t\tinfo->far_ptr = & ((M_%s *)node)->%s;\n", n->name, bf->name);
747 } else {
748 char szName[20];
749 strcpy(szName, bf->familly);
750 strupr(szName);
751 //no ext type
752 fprintf(f, "\t\tinfo->fieldType = GF_SG_VRML_%s;\n", szName);
753 fprintf(f, "\t\tinfo->far_ptr = & ((M_%s *) node)->%s;\n", n->name, bf->name);
754 }
755 fprintf(f, "\t\treturn GF_OK;\n");
756 }
757 fprintf(f, "\tdefault:\n\t\treturn GF_BAD_PARAM;\n\t}\n}\n\n");
758
759 fprintf(f, "\nstatic s32 %s_get_field_index_by_name(char *name)\n{\n", n->name);
760 for (i=0; i<gf_list_count(n->Fields); i++) {
761 bf = gf_list_get(n->Fields, i);
762 fprintf(f, "\tif (!strcmp(\"%s\", name)) return %d;\n", (bf->name[0]=='_') ? bf->name+1 : bf->name, i);
763 }
764 fprintf(f, "\treturn -1;\n\t}\n");
765 }
766
767
768 //write the Quantization info for each node field(Quant and BIFS-Anim info)
WriteNodeQuant(FILE * f,BNode * n)769 void WriteNodeQuant(FILE *f, BNode *n)
770 {
771 u32 i;
772 fprintf(f, "static Bool %s_get_aq_info(GF_Node *n, u32 FieldIndex, u8 *QType, u8 *AType, Fixed *b_min, Fixed *b_max, u32 *QT13_bits)\n{\n\tswitch (FieldIndex) {\n", n->name);
773
774 for (i=0; i<gf_list_count(n->Fields) ; i++ ) {
775 BField *bf = gf_list_get(n->Fields, i);
776 if (!bf->hasAnim && !bf->hasQuant) continue;
777
778 fprintf(f, "\tcase %d:\n", i);
779 //Anim Type
780 fprintf(f, "\t\t*AType = %d;\n", bf->AnimType);
781 //Quant Type
782 fprintf(f, "\t\t*QType = %s;\n", bf->quant_type);
783 if (!strcmp(bf->quant_type, "13"))
784 fprintf(f, "\t\t*QT13_bits = %s;\n", bf->qt13_bits);
785
786 //Bounds
787 if (bf->hasBounds) {
788 if (!strcmp(bf->b_min, "+I") || !strcmp(bf->b_min, " +I") || !strcmp(bf->b_min, "I")) {
789 fprintf(f, "\t\t*b_min = FIX_MAX;\n");
790 } else if (!strcmp(bf->b_min, "-I") || !strcmp(bf->b_min, "-65536")) {
791 fprintf(f, "\t\t*b_min = FIX_MIN;\n");
792 } else {
793 fprintf(f, "\t\t*b_min = %s;\n", GetFixedPrintout(bf->b_min));
794 }
795 if (!strcmp(bf->b_max, "+I") || !strcmp(bf->b_max, " +I") || !strcmp(bf->b_max, "I") || !strcmp(bf->b_max, "65535")) {
796 fprintf(f, "\t\t*b_max = FIX_MAX;\n");
797 } else {
798 fprintf(f, "\t\t*b_max = %s;\n", GetFixedPrintout(bf->b_max));
799 }
800 }
801 fprintf(f, "\t\treturn 1;\n");
802 }
803 fprintf(f, "\tdefault:\n\t\treturn 0;\n\t}\n}\n\n");
804 }
805
WriteNodeCode(GF_List * BNodes)806 void WriteNodeCode(GF_List *BNodes)
807 {
808 FILE *f;
809 char token[20], tok[20];
810 char *store;
811 u32 i, j, k, go;
812 BField *bf;
813 BNode *n;
814
815 f = BeginFile("mpeg4_nodes", 1);
816
817 fprintf(f, "#include <gpac/nodes_mpeg4.h>\n\n");
818 fprintf(f, "\n#include <gpac/internal/scenegraph_dev.h>\n");
819
820 fprintf(f, "\n#ifndef GPAC_DISABLE_VRML\n");
821
822
823 for (k=0; k<gf_list_count(BNodes); k++) {
824 Bool is_parent = 0;
825 n = gf_list_get(BNodes, k);
826
827 if (n->skip_impl) continue;
828
829 fprintf(f, "\n/*\n\t%s Node deletion\n*/\n\n", n->name);
830 fprintf(f, "static void %s_Del(GF_Node *node)\n{\n\tM_%s *p = (M_%s *) node;\n", n->name, n->name, n->name);
831
832 for (i=0; i<gf_list_count(n->Fields); i++) {
833 bf = gf_list_get(n->Fields, i);
834 //nothing on child events
835 if (!strcmp(bf->name, "addChildren")) continue;
836 if (!strcmp(bf->name, "removeChildren")) continue;
837
838 //delete all children node
839 if (!strcmp(bf->name, "children") && stricmp(n->name, "audioBuffer")) {
840 is_parent = 1;
841 continue;
842 }
843
844 //delete ALL fields that must be deleted: this includes eventIn and out since
845 //all fields are defined in the node
846 if (!strcmp(bf->familly, "MFInt")
847 || !strcmp(bf->familly, "MFFloat")
848 || !strcmp(bf->familly, "MFDouble")
849 || !strcmp(bf->familly, "MFBool")
850 || !strcmp(bf->familly, "MFInt32")
851 || !strcmp(bf->familly, "MFColor")
852 || !strcmp(bf->familly, "MFRotation")
853 || !strcmp(bf->familly, "MFString")
854 || !strcmp(bf->familly, "MFTime")
855 || !strcmp(bf->familly, "MFVec2f")
856 || !strcmp(bf->familly, "MFVec3f")
857 || !strcmp(bf->familly, "MFVec4f")
858 || !strcmp(bf->familly, "MFVec2d")
859 || !strcmp(bf->familly, "MFVec3d")
860 || !strcmp(bf->familly, "MFURL")
861 || !strcmp(bf->familly, "MFScript")
862 || !strcmp(bf->familly, "SFString")
863 || !strcmp(bf->familly, "SFURL")
864 || !strcmp(bf->familly, "SFImage")
865 || !strcmp(bf->familly, "MFAttrRef")
866 ) {
867 char szName[500];
868 strcpy(szName, bf->familly);
869 strlwr(szName);
870 fprintf(f, "\tgf_sg_%s_del(p->%s);\n", szName, bf->name);
871 }
872 else if (!strcmp(bf->familly, "SFCommandBuffer")) {
873 fprintf(f, "\tgf_sg_sfcommand_del(p->%s);\n", bf->name);
874 }
875 else if (strstr(bf->familly, "Node")) {
876 //this is a POINTER to a node
877 if (strstr(bf->familly, "SF")) {
878 fprintf(f, "\tgf_node_unregister((GF_Node *) p->%s, (GF_Node *) p);\t\n", bf->name);
879 } else {
880 //this is a POINTER to a chain
881 fprintf(f, "\tgf_node_unregister_children((GF_Node *) p, p->%s);\t\n", bf->name);
882 }
883 }
884 }
885 if (!strcmp(n->name, "CacheTexture")) {
886 fprintf(f, "\tif (p->data) gf_free(p->data);\n");
887 }
888 if (is_parent) fprintf(f, "\tgf_sg_vrml_parent_destroy((GF_Node *) p);\t\n");
889 fprintf(f, "\tgf_node_free((GF_Node *) p);\n}\n\n");
890
891 //node fields
892 WriteNodeFields(f, n);
893 WriteNodeQuant(f, n);
894
895 //
896 // Constructor
897 //
898
899 fprintf(f, "\n\nGF_Node *%s_Create()\n{\n\tM_%s *p;\n\tGF_SAFEALLOC(p, M_%s);\n", n->name, n->name, n->name);
900 fprintf(f, "\tif(!p) return NULL;\n");
901 fprintf(f, "\tgf_node_setup((GF_Node *)p, TAG_MPEG4_%s);\n", n->name);
902
903 for (i=0; i<gf_list_count(n->Fields); i++) {
904 bf = gf_list_get(n->Fields, i);
905 //setup all children node
906 if (!strcmp(bf->name, "children") && stricmp(n->name, "audioBuffer")) {
907 fprintf(f, "\tgf_sg_vrml_parent_setup((GF_Node *) p);\n");
908 break;
909 }
910 else if ( strstr(bf->familly, "Node") && strncmp(bf->type, "event", 5) ) {
911 #if 0
912 //this is a POINTER to a node
913 if (strstr(bf->familly, "MF")) {
914 //this is a POINTER to a chain
915 fprintf(f, "\tp->%s = gf_list_new();\t\n", bf->name);
916 }
917 #endif
918 }
919 /*special case for SFCommandBuffer: we also create a command list*/
920 if (!stricmp(bf->familly, "SFCommandBuffer")) {
921 fprintf(f, "\tp->%s.commandList = gf_list_new();\t\n", bf->name);
922 }
923 }
924
925 //check if we have a child node
926 for (i=0; i<gf_list_count(n->Fields); i++) {
927 bf = gf_list_get(n->Fields, i);
928 if ( !strcmp(bf->name, "children") ||
929 ( !strstr(bf->type, "event") && strstr(bf->familly, "MF") && strstr(bf->familly, "Node")) ) {
930 sprintf(n->Child_NDT_Name, "NDT_SF%s", bf->familly+2);
931 break;
932 }
933 }
934
935 fprintf(f, "\n\t/*default field values*/\n");
936
937 for (i=0; i<gf_list_count(n->Fields); i++) {
938 bf = gf_list_get(n->Fields, i);
939
940 //nothing on eventIn or Out
941 if (!strcmp(bf->type, "eventIn")) continue;
942 if (!strcmp(bf->type, "eventOut")) continue;
943
944 if (!strcmp(bf->def, "")) continue;
945
946 //no default on nodes
947 if (strstr(bf->familly, "Node")) continue;
948 //extract default falue
949
950 //
951 // SF Fields
952 //
953
954 //SFBool
955 if (!strcmp(bf->familly, "SFBool")) {
956 if (!strcmp(bf->def, "1") || !strcmp(bf->def, "TRUE"))
957 fprintf(f, "\tp->%s = 1;\n", bf->name);
958 }
959 //SFFloat
960 else if (!strcmp(bf->familly, "SFFloat")) {
961 fprintf(f, "\tp->%s = %s;\n", bf->name, GetFixedPrintout(bf->def));
962 }
963 //SFTime
964 else if (!strcmp(bf->familly, "SFTime")) {
965 fprintf(f, "\tp->%s = %s;\n", bf->name, bf->def);
966 }
967 //SFInt32
968 else if (!strcmp(bf->familly, "SFInt32")) {
969 fprintf(f, "\tp->%s = %s;\n", bf->name, bf->def);
970 }
971 //SFURL
972 else if (!strcmp(bf->familly, "SFURL")) {
973 if (strcmp(bf->def, "NULL"))
974 fprintf(f, "\tp->%s = %s;\n", bf->name, bf->def);
975 }
976 //SFColor
977 else if (!strcmp(bf->familly, "SFColor")) {
978 CurrentLine = bf->def;
979 GetNextToken(token, " ");
980 TranslateToken(token);
981
982 fprintf(f, "\tp->%s.red = %s;\n", bf->name, GetFixedPrintout(token));
983 GetNextToken(token, " ");
984 fprintf(f, "\tp->%s.green = %s;\n", bf->name, GetFixedPrintout(token));
985 GetNextToken(token, " ");
986 fprintf(f, "\tp->%s.blue = %s;\n", bf->name, GetFixedPrintout(token));
987 }
988 //SFVec2f
989 else if (!strcmp(bf->familly, "SFVec2f")) {
990 CurrentLine = bf->def;
991 GetNextToken(token, " ");
992 TranslateToken(token);
993 fprintf(f, "\tp->%s.x = %s;\n", bf->name, GetFixedPrintout(token));
994 GetNextToken(token, " ");
995 TranslateToken(token);
996 fprintf(f, "\tp->%s.y = %s;\n", bf->name, GetFixedPrintout(token));
997 }
998 //SFVec3f
999 else if (!strcmp(bf->familly, "SFVec3f")) {
1000 CurrentLine = bf->def;
1001 GetNextToken(token, " ");
1002 TranslateToken(token);
1003 fprintf(f, "\tp->%s.x = %s;\n", bf->name, GetFixedPrintout(token));
1004
1005 GetNextToken(token, " ");
1006 TranslateToken(token);
1007 fprintf(f, "\tp->%s.y = %s;\n", bf->name, GetFixedPrintout(token));
1008
1009 GetNextToken(token, " ");
1010 TranslateToken(token);
1011 fprintf(f, "\tp->%s.z = %s;\n", bf->name, GetFixedPrintout(token));
1012 }
1013 //SFVec4f & SFRotation
1014 else if (!strcmp(bf->familly, "SFVec4f") || !strcmp(bf->familly, "SFRotation")) {
1015 CurrentLine = bf->def;
1016 GetNextToken(token, " ");
1017 TranslateToken(token);
1018 fprintf(f, "\tp->%s.x = %s;\n", bf->name, GetFixedPrintout(token));
1019
1020 GetNextToken(token, " ");
1021 TranslateToken(token);
1022 fprintf(f, "\tp->%s.y = %s;\n", bf->name, GetFixedPrintout(token));
1023
1024 GetNextToken(token, " ");
1025 TranslateToken(token);
1026 fprintf(f, "\tp->%s.z = %s;\n", bf->name, GetFixedPrintout(token));
1027
1028 GetNextToken(token, " ");
1029 TranslateToken(token);
1030 fprintf(f, "\tp->%s.q = %s;\n", bf->name, GetFixedPrintout(token));
1031 }
1032 //SFString
1033 else if (!strcmp(bf->familly, "SFString")) {
1034 fprintf(f, "\tp->%s.buffer = (char*)gf_malloc(sizeof(char) * %u);\n", bf->name, (u32) strlen(bf->def)+1);
1035 fprintf(f, "\tstrcpy(p->%s.buffer, \"%s\");\n", bf->name, bf->def);
1036 }
1037
1038 //
1039 // MF Fields
1040 //
1041 //MFFloat
1042 else if (!strcmp(bf->familly, "MFFloat")) {
1043 j = 0;
1044 CurrentLine = bf->def;
1045 while (GetNextToken(token, " ,")) j++;
1046 j+=1;
1047 fprintf(f, "\tp->%s.vals = (SFFloat*)gf_malloc(sizeof(SFFloat)*%d);\n", bf->name, j);
1048 fprintf(f, "\tp->%s.count = %d;\n", bf->name, j);
1049 j = 0;
1050 go = 1;
1051 CurrentLine = bf->def;
1052 while (go) {
1053 if (!GetNextToken(token, " ,")) go = 0;
1054 TranslateToken(token);
1055 fprintf(f, "\tp->%s.vals[%d] = %s;\n", bf->name, j, GetFixedPrintout(token));
1056 j+=1;
1057 }
1058 }
1059 //MFVec2f
1060 else if (!strcmp(bf->familly, "MFVec2f")) {
1061 j = 0;
1062 CurrentLine = bf->def;
1063 while (GetNextToken(token, ",")) j++;
1064 j+=1;
1065 fprintf(f, "\tp->%s.vals = (SFVec2f*)gf_malloc(sizeof(SFVec2f)*%d);\n", bf->name, j);
1066 fprintf(f, "\tp->%s.count = %d;\n", bf->name, j);
1067 j = 0;
1068 go = 1;
1069 CurrentLine = bf->def;
1070 while (go) {
1071 if (!GetNextToken(token, ",")) go = 0;
1072 store = CurrentLine;
1073 CurrentLine = token;
1074 GetNextToken(tok, " ");
1075 TranslateToken(tok);
1076 fprintf(f, "\tp->%s.vals[%d].x = %s;\n", bf->name, j, GetFixedPrintout(tok));
1077 GetNextToken(tok, " ");
1078 TranslateToken(tok);
1079 fprintf(f, "\tp->%s.vals[%d].y = %s;\n", bf->name, j, GetFixedPrintout(tok));
1080 j+=1;
1081 CurrentLine = store;
1082 }
1083 }
1084 //MFVec3f
1085 else if (!strcmp(bf->familly, "MFVec3f")) {
1086 j = 0;
1087 CurrentLine = bf->def;
1088 while (GetNextToken(token, ",")) j++;
1089 j+=1;
1090 fprintf(f, "\tp->%s.vals = (SFVec3f *)gf_malloc(sizeof(SFVec3f)*%d);\n", bf->name, j);
1091 fprintf(f, "\tp->%s.count = %d;\n", bf->name, j);
1092 j = 0;
1093 go = 1;
1094 CurrentLine = bf->def;
1095 while (go) {
1096 if (!GetNextToken(token, ",")) go = 0;
1097 store = CurrentLine;
1098 CurrentLine = token;
1099 GetNextToken(tok, " ");
1100 TranslateToken(tok);
1101 fprintf(f, "\tp->%s.vals[%d].x = %s;\n", bf->name, j, GetFixedPrintout(tok));
1102 GetNextToken(tok, " ");
1103 TranslateToken(tok);
1104 fprintf(f, "\tp->%s.vals[%d].y = %s;\n", bf->name, j, GetFixedPrintout(tok));
1105 GetNextToken(tok, " ");
1106 TranslateToken(tok);
1107 fprintf(f, "\tp->%s.vals[%d].z = %s;\n", bf->name, j, GetFixedPrintout(tok));
1108 j+=1;
1109 CurrentLine = store;
1110 }
1111 }
1112 //MFVec4f
1113 else if (!strcmp(bf->familly, "MFVec4f") || !strcmp(bf->familly, "MFRotation")) {
1114 j = 0;
1115 CurrentLine = bf->def;
1116 while (GetNextToken(token, ",")) j++;
1117 j+=1;
1118 fprintf(f, "\tp->%s.vals = (GF_Vec4*)gf_malloc(sizeof(GF_Vec4)*%d);\n", bf->name, j);
1119 fprintf(f, "\tp->%s.count = %d;\n", bf->name, j);
1120 j = 0;
1121 go = 1;
1122 CurrentLine = bf->def;
1123 while (go) {
1124 if (!GetNextToken(token, ",")) go = 0;
1125 store = CurrentLine;
1126 CurrentLine = token;
1127 GetNextToken(tok, " ");
1128 TranslateToken(tok);
1129 fprintf(f, "\tp->%s.vals[%d].x = %s;\n", bf->name, j, GetFixedPrintout(tok));
1130 GetNextToken(tok, " ");
1131 TranslateToken(tok);
1132 fprintf(f, "\tp->%s.vals[%d].y = %s;\n", bf->name, j, GetFixedPrintout(tok));
1133 GetNextToken(tok, " ");
1134 TranslateToken(tok);
1135 fprintf(f, "\tp->%s.vals[%d].z = %s;\n", bf->name, j, GetFixedPrintout(tok));
1136 GetNextToken(tok, " ");
1137 TranslateToken(tok);
1138 fprintf(f, "\tp->%s.vals[%d].q = %s;\n", bf->name, j, GetFixedPrintout(tok));
1139 j+=1;
1140 CurrentLine = store;
1141 }
1142 }
1143 //MFInt32
1144 else if (!strcmp(bf->familly, "MFInt32")) {
1145 j = 0;
1146 CurrentLine = bf->def;
1147 while (GetNextToken(token, ",")) j++;
1148 j+=1;
1149 fprintf(f, "\tp->%s.vals = (SFInt32*)gf_malloc(sizeof(SFInt32)*%d);\n", bf->name, j);
1150 fprintf(f, "\tp->%s.count = %d;\n", bf->name, j);
1151 j = 0;
1152 go = 1;
1153 CurrentLine = bf->def;
1154 while (go) {
1155 if (!GetNextToken(token, ",")) go = 0;
1156 store = CurrentLine;
1157 CurrentLine = token;
1158 GetNextToken(tok, " ");
1159 fprintf(f, "\tp->%s.vals[%d] = %s;\n", bf->name, j, tok);
1160 j+=1;
1161 CurrentLine = store;
1162 }
1163 }
1164 //MFColor
1165 else if (!strcmp(bf->familly, "MFColor")) {
1166 j = 0;
1167 CurrentLine = bf->def;
1168 while (GetNextToken(token, ",")) j++;
1169 j+=1;
1170 fprintf(f, "\tp->%s.vals = (SFColor*)gf_malloc(sizeof(SFColor)*%d);\n", bf->name, j);
1171 fprintf(f, "\tp->%s.count = %d;\n", bf->name, j);
1172 j = 0;
1173 go = 1;
1174 CurrentLine = bf->def;
1175 while (go) {
1176 if (!GetNextToken(token, ",")) go = 0;
1177 store = CurrentLine;
1178 CurrentLine = token;
1179 GetNextToken(tok, " ");
1180 fprintf(f, "\tp->%s.vals[%d].red = %s;\n", bf->name, j, GetFixedPrintout(tok));
1181 GetNextToken(tok, " ");
1182 fprintf(f, "\tp->%s.vals[%d].green = %s;\n", bf->name, j, GetFixedPrintout(tok));
1183 GetNextToken(tok, " ");
1184 fprintf(f, "\tp->%s.vals[%d].blue = %s;\n", bf->name, j, GetFixedPrintout(tok));
1185 j+=1;
1186 CurrentLine = store;
1187 }
1188 }
1189 //MFString
1190 else if (!strcmp(bf->familly, "MFString")) {
1191 j = 0;
1192 CurrentLine = bf->def;
1193 while (GetNextToken(token, ",")) j++;
1194 j+=1;
1195 fprintf(f, "\tp->%s.vals = (char**)gf_malloc(sizeof(SFString)*%d);\n", bf->name, j);
1196 fprintf(f, "\tp->%s.count = %d;\n", bf->name, j);
1197 j = 0;
1198 go = 1;
1199 CurrentLine = bf->def;
1200 while (go) {
1201 if (!GetNextToken(token, ",")) go = 0;
1202 store = CurrentLine;
1203 CurrentLine = token;
1204 GetNextToken(tok, " \"");
1205 fprintf(f, "\tp->%s.vals[%d] = (char*)gf_malloc(sizeof(char) * %u);\n", bf->name, j, (u32) strlen(tok)+1);
1206 fprintf(f, "\tstrcpy(p->%s.vals[%d], \"%s\");\n", bf->name, j, tok);
1207 j+=1;
1208 CurrentLine = store;
1209 }
1210 }
1211 //MFTime
1212 else if (!strcmp(bf->familly, "MFTime")) {
1213 j = 0;
1214 CurrentLine = bf->def;
1215 while (GetNextToken(token, ",")) j++;
1216 j+=1;
1217 fprintf(f, "\tp->%s.vals = (SFTime*)gf_malloc(sizeof(SFTime)*%d);\n", bf->name, j);
1218 fprintf(f, "\tp->%s.count = %d;\n", bf->name, j);
1219 j = 0;
1220 go = 1;
1221 CurrentLine = bf->def;
1222 while (go) {
1223 if (!GetNextToken(token, ",")) go = 0;
1224 store = CurrentLine;
1225 CurrentLine = token;
1226 GetNextToken(tok, " \"");
1227 TranslateToken(tok);
1228 fprintf(f, "\tp->%s.vals[%d] = %s;\n", bf->name, j, tok);
1229 j+=1;
1230 CurrentLine = store;
1231 }
1232 }
1233
1234 //other nodes
1235 else if (!strcmp(bf->familly, "SFImage")) {
1236 //we currently only have SFImage, with NO texture so do nothing
1237 }
1238 //unknown init (for debug)
1239 else {
1240 fprintf(f, "UNKNOWN FIELD (%s);\n", bf->familly);
1241
1242 }
1243 }
1244 fprintf(f, "\treturn (GF_Node *)p;\n}\n\n");
1245
1246 }
1247
1248 fprintf(f, "\n\n\n");
1249
1250 //creator function
1251 fprintf(f, "GF_Node *gf_sg_mpeg4_node_new(u32 NodeTag)\n{\n\tswitch (NodeTag) {\n");
1252 for (i=0; i<gf_list_count(BNodes); i++) {
1253 n = gf_list_get(BNodes, i);
1254 if (!n->skip_impl) {
1255 fprintf(f, "\tcase TAG_MPEG4_%s:\n\t\treturn %s_Create();\n", n->name, n->name);
1256 }
1257 }
1258 fprintf(f, "\tdefault:\n\t\treturn NULL;\n\t}\n}\n\n");
1259
1260 fprintf(f, "const char *gf_sg_mpeg4_node_get_class_name(u32 NodeTag)\n{\n\tswitch (NodeTag) {\n");
1261 for (i=0; i<gf_list_count(BNodes); i++) {
1262 n = gf_list_get(BNodes, i);
1263 if (!n->skip_impl) fprintf(f, "\tcase TAG_MPEG4_%s:\n\t\treturn \"%s\";\n", n->name, n->name);
1264 }
1265 fprintf(f, "\tdefault:\n\t\treturn \"Unknown Node\";\n\t}\n}\n\n");
1266
1267 fprintf(f, "void gf_sg_mpeg4_node_del(GF_Node *node)\n{\n\tswitch (node->sgprivate->tag) {\n");
1268 for (i=0; i<gf_list_count(BNodes); i++) {
1269 n = gf_list_get(BNodes, i);
1270 if (!n->skip_impl) {
1271 fprintf(f, "\tcase TAG_MPEG4_%s:\n\t\t%s_Del(node); return;\n", n->name, n->name);
1272 }
1273 }
1274 fprintf(f, "\tdefault:\n\t\treturn;\n\t}\n}\n\n");
1275
1276 fprintf(f, "u32 gf_sg_mpeg4_node_get_field_count(GF_Node *node, u8 code_mode)\n{\n\tswitch (node->sgprivate->tag) {\n");
1277 for (i=0; i<gf_list_count(BNodes); i++) {
1278 n = gf_list_get(BNodes, i);
1279 if (!n->skip_impl) {
1280 fprintf(f, "\tcase TAG_MPEG4_%s:return %s_get_field_count(node, code_mode);\n", n->name, n->name);
1281 }
1282 }
1283 fprintf(f, "\tdefault:\n\t\treturn 0;\n\t}\n}\n\n");
1284
1285 fprintf(f, "GF_Err gf_sg_mpeg4_node_get_field(GF_Node *node, GF_FieldInfo *field)\n{\n\tswitch (node->sgprivate->tag) {\n");
1286 for (i=0; i<gf_list_count(BNodes); i++) {
1287 n = gf_list_get(BNodes, i);
1288 if (!n->skip_impl) {
1289 fprintf(f, "\tcase TAG_MPEG4_%s: return %s_get_field(node, field);\n", n->name, n->name);
1290 }
1291 }
1292 fprintf(f, "\tdefault:\n\t\treturn GF_BAD_PARAM;\n\t}\n}\n\n");
1293
1294 fprintf(f, "GF_Err gf_sg_mpeg4_node_get_field_index(GF_Node *node, u32 inField, u8 code_mode, u32 *fieldIndex)\n{\n\tswitch (node->sgprivate->tag) {\n");
1295 for (i=0; i<gf_list_count(BNodes); i++) {
1296 n = gf_list_get(BNodes, i);
1297 if (!n->skip_impl) {
1298 fprintf(f, "\tcase TAG_MPEG4_%s: return %s_get_field_index(node, inField, code_mode, fieldIndex);\n", n->name, n->name);
1299 }
1300 }
1301 fprintf(f, "\tdefault:\n\t\treturn GF_BAD_PARAM;\n\t}\n}\n\n");
1302
1303 fprintf(f, "Bool gf_sg_mpeg4_node_get_aq_info(GF_Node *node, u32 FieldIndex, u8 *QType, u8 *AType, Fixed *b_min, Fixed *b_max, u32 *QT13_bits)\n{\n\tswitch (node->sgprivate->tag) {\n");
1304 for (i=0; i<gf_list_count(BNodes); i++) {
1305 n = gf_list_get(BNodes, i);
1306 if (!n->skip_impl) {
1307 fprintf(f, "\tcase TAG_MPEG4_%s: return %s_get_aq_info(node, FieldIndex, QType, AType, b_min, b_max, QT13_bits);\n", n->name, n->name);
1308 }
1309 }
1310 fprintf(f, "\tdefault:\n\t\treturn 0;\n\t}\n}\n\n");
1311
1312 fprintf(f, "u32 gf_sg_mpeg4_node_get_child_ndt(GF_Node *node)\n{\n\tswitch (node->sgprivate->tag) {\n");
1313 for (i=0; i<gf_list_count(BNodes); i++) {
1314 n = gf_list_get(BNodes, i);
1315 if (!n->skip_impl && strlen(n->Child_NDT_Name) ) {
1316 fprintf(f, "\tcase TAG_MPEG4_%s: return %s;\n", n->name, n->Child_NDT_Name);
1317 }
1318 }
1319 fprintf(f, "\tdefault:\n\t\treturn 0;\n\t}\n}\n\n");
1320
1321
1322 fprintf(f, "\nu32 gf_node_mpeg4_type_by_class_name(const char *node_name)\n{\n\tif(!node_name) return 0;\n");
1323 for (i=0; i<gf_list_count(BNodes); i++) {
1324 n = gf_list_get(BNodes, i);
1325 if (n->skip_impl) continue;
1326 fprintf(f, "\tif (!strcmp(node_name, \"%s\")) return TAG_MPEG4_%s;\n", n->name, n->name);
1327 }
1328 fprintf(f, "\treturn 0;\n}\n\n");
1329
1330 fprintf(f, "s32 gf_sg_mpeg4_node_get_field_index_by_name(GF_Node *node, char *name)\n{\n\tswitch (node->sgprivate->tag) {\n");
1331 for (i=0; i<gf_list_count(BNodes); i++) {
1332 n = gf_list_get(BNodes, i);
1333 if (!n->skip_impl) {
1334 fprintf(f, "\tcase TAG_MPEG4_%s: return %s_get_field_index_by_name(name);\n", n->name, n->name);
1335 }
1336 }
1337 fprintf(f, "\tdefault:\n\t\treturn -1;\n\t}\n}\n\n");
1338
1339 fprintf(f, "\n#endif /*GPAC_DISABLE_VRML*/\n");
1340
1341 EndFile(f, "", 1);
1342 }
1343
ParseTemplateFile(FILE * nodes,GF_List * BNodes,GF_List * NDTs,u32 version)1344 void ParseTemplateFile(FILE *nodes, GF_List *BNodes, GF_List *NDTs, u32 version)
1345 {
1346 char sLine[2000];
1347 char token[100];
1348 char *p;
1349 BNode *n;
1350 BField *f;
1351 u32 j, i, k;
1352
1353 //get lines one by one
1354 n = NULL;
1355 while (!feof(nodes)) {
1356 fgets(sLine, 2000, nodes);
1357 //skip comment and empty lines
1358 if (sLine[0] == '#') continue;
1359 if (sLine[0] == '\n') continue;
1360
1361 CurrentLine = sLine;
1362
1363 //parse the line till end of line
1364 while (GetNextToken(token, " \t")) {
1365
1366 //this is a new node
1367 if (!strcmp(token, "PROTO") ) {
1368 n = BlankNode();
1369 n->version = version;
1370 gf_list_add(BNodes, n);
1371
1372 //get its name
1373 GetNextToken(n->name, " \t[");
1374 //extract the NDTs
1375 GetNextToken(token, "\t[ %#=");
1376 if (strcmp(token, "NDT")) {
1377 printf("Corrupted template file\n");
1378 return;
1379 }
1380 while (1) {
1381 GetNextToken(token, "=, \t");
1382 //done with NDTs
1383 if (token[0] == '%') break;
1384
1385 //update the NDT list
1386 CheckInTable(token, NDTs);
1387 p = gf_malloc(strlen(token)+1);
1388 strcpy(p, token);
1389 gf_list_add(n->NDT, p);
1390 }
1391
1392 //extract the coding type
1393 if (strcmp(token, "%COD")) {
1394 printf("Corrupted template file\n");
1395 return;
1396 } else {
1397 GetNextToken(token, "= ");
1398 if (token[0] == 'N') {
1399 n->codingType = 0;
1400 } else {
1401 n->codingType = 1;
1402 }
1403 }
1404 }
1405 //this is NOT a field
1406 else if (token[0] == ']' || token[0] == '{' || token[0] == '}' ) {
1407 break;
1408 }
1409 //parse a field
1410 else {
1411 if (!n) {
1412 printf("Corrupted template file\n");
1413 return;
1414 }
1415 f = BlankField();
1416 gf_list_add(n->Fields, f);
1417
1418 //get the field type
1419 strcpy(f->type, token);
1420 GetNextToken(f->familly, " \t");
1421 GetNextToken(f->name, " \t");
1422 //fix for our own code :(
1423 if (!strcmp(f->name, "tag")) strcpy(f->name, "_tag");
1424 if (!strcmp(f->name, "auto")) strcpy(f->name, "_auto");
1425
1426 //has default
1427 skip_sep(" \t");
1428 if (GetNextToken(token, "#\t")) {
1429 j=0;
1430 while (token[j] == ' ') j+=1;
1431 if (token[j] == '[') j+=1;
1432 if (token[j] == '"') j+=1;
1433
1434 if (token[j] != '"' && token[j] != ']') {
1435 strcpy(f->def, token+j);
1436 j=1;
1437 while (j) {
1438 switch (f->def[strlen(f->def)-1]) {
1439 case ' ':
1440 case '"':
1441 case ']':
1442 f->def[strlen(f->def)-1] = 0;
1443 break;
1444 default:
1445 j=0;
1446 break;
1447 }
1448 }
1449 } else {
1450 strcpy(f->def, "");
1451 }
1452 if (!strcmp(f->familly, "SFFloat")) {
1453 if (!strcmp(f->def, "+I") || !strcmp(f->def, "I")) {
1454 strcpy(f->def, "FIX_MAX");
1455 } else if (!strcmp(f->def, "-I")) {
1456 strcpy(f->def, "FIX_MIN");
1457 }
1458 } else if (!strcmp(f->familly, "SFTime")) {
1459 if (!strcmp(f->def, "+I") || !strcmp(f->def, "I")) {
1460 strcpy(f->def, "FIX_MAX");
1461 } else if (!strcmp(f->def, "-I")) {
1462 strcpy(f->def, "FIX_MIN");
1463 }
1464 } else if (!strcmp(f->familly, "SFInt32")) {
1465 if (!strcmp(f->def, "+I") || !strcmp(f->def, "I")) {
1466 strcpy(f->def, "0x80000000");
1467 } else if (!strcmp(f->def, "-I")) {
1468 strcpy(f->def, "GF_INT_MIN");
1469 }
1470 }
1471 }
1472 //has other
1473 while (GetNextToken(token, " \t#%=")) {
1474 switch (token[0]) {
1475 //bounds
1476 case 'b':
1477 f->hasBounds = 1;
1478 GetNextToken(f->b_min, "[(,");
1479 GetNextToken(f->b_max, ")]");
1480 break;
1481 case 'q':
1482 f->hasQuant = 1;
1483 GetNextToken(f->quant_type, " \t");
1484 if (!strcmp(f->quant_type, "13"))
1485 GetNextToken(f->qt13_bits, " \t");
1486 break;
1487 case 'a':
1488 f->hasAnim = 1;
1489 GetNextToken(token, " \t");
1490 f->AnimType = atoi(token);
1491 break;
1492 default:
1493 break;
1494 }
1495 }
1496 }
1497 }
1498 }
1499
1500
1501 for (k=0; k<gf_list_count(BNodes); k++) {
1502 n = gf_list_get(BNodes, k);
1503
1504 for (i=0; i<gf_list_count(n->Fields); i++) {
1505 f = gf_list_get(n->Fields, i);
1506 //nothing on events
1507 if (!strcmp(f->type, "eventIn")) continue;
1508 if (!strcmp(f->type, "eventOut")) continue;
1509 if (!strcmp(f->def, "")) continue;
1510 if (strstr(f->familly, "Node")) continue;
1511 n->hasDefault = 1;
1512 }
1513 }
1514 }
1515
1516
WriteNodeDump(FILE * f,BNode * n)1517 void WriteNodeDump(FILE *f, BNode *n)
1518 {
1519 u32 i;
1520
1521 fprintf(f, "static const char *%s_FieldName[] = {\n", n->name);
1522 for (i=0; i<gf_list_count(n->Fields); i++) {
1523 BField *bf = gf_list_get(n->Fields, i);
1524 if (!i) {
1525 fprintf(f, " \"%s\"", bf->name);
1526 } else {
1527 fprintf(f, ", \"%s\"", bf->name);
1528 }
1529 }
1530 fprintf(f, "\n};\n\n");
1531 }
1532
parse_profile(GF_List * nodes,FILE * prof)1533 void parse_profile(GF_List *nodes, FILE *prof)
1534 {
1535 char sLine[2000];
1536 BNode *n;
1537 Bool found;
1538 u32 i;
1539
1540 while (!feof(prof)) {
1541 fgets(sLine, 2000, prof);
1542 //skip comment and empty lines
1543 if (sLine[0] == '#') continue;
1544 if (sLine[0] == '\n') continue;
1545 if (strstr(sLine, "Proximity"))
1546 found = 0;
1547 found = 1;
1548 while (found) {
1549 switch (sLine[strlen(sLine)-1]) {
1550 case '\n':
1551 case '\r':
1552 case ' ':
1553 sLine[strlen(sLine)-1] = 0;
1554 break;
1555 default:
1556 found = 0;
1557 break;
1558 }
1559 }
1560
1561 // if (0 && !stricmp(sLine, "Appearance") || !stricmp(sLine, "Shape") || !stricmp(sLine, "Sound2D") ) {
1562 if (0) {
1563 printf("Warning: cannot disable node %s (required in all BIFS profiles)\n", sLine);
1564 } else {
1565 found = 0;
1566 for (i=0; i<gf_list_count(nodes); i++) {
1567 n = gf_list_get(nodes, i);
1568 if (!stricmp(n->name, sLine)) {
1569 n->skip_impl = 1;
1570 found = 1;
1571 break;
1572 }
1573 }
1574 if (!found) printf("cannot disable %s: node not found\n", sLine);
1575 }
1576 }
1577 }
1578
format_bit_string(char * str,u32 val,u32 nb_bits)1579 char *format_bit_string(char *str, u32 val, u32 nb_bits)
1580 {
1581 u32 i, len;
1582 strcpy(str, "");
1583 while (nb_bits) {
1584 strcat(str, (val%2) ? "1" : "0");
1585 val>>=1;
1586 nb_bits--;
1587 }
1588 len = strlen(str);
1589 for (i=0; i<len/2; i++) {
1590 char c = str[i];
1591 str[i] = str[len-i-1];
1592 str[len-i-1]=c;
1593 }
1594 return str;
1595 }
1596
get_nb_bits(u32 MaxVal)1597 u32 get_nb_bits(u32 MaxVal)
1598 {
1599 u32 k=1;
1600 if (!MaxVal) return 0;
1601 MaxVal--;
1602 while (MaxVal > ((1<<k)-1) ) k+=1;
1603 return k;
1604 }
1605
generate_ndts(GF_List * NDTs,GF_List * nodes,u32 nbVersion)1606 void generate_ndts(GF_List *NDTs, GF_List *nodes, u32 nbVersion)
1607 {
1608 u32 nb_nodes, nb_ndt, i, j, k, nb_bits, idx, l;
1609 char szStr[100];
1610 nb_ndt = gf_list_count(NDTs);
1611 nb_nodes = gf_list_count(nodes);
1612 for (i=0; i<nbVersion; i++) {
1613 char szFile[100];
1614 FILE *f;
1615 sprintf(szFile, "NdtListV%d.html", i+1);
1616 f = gf_fopen(szFile, "wt");
1617
1618 fprintf(f, "<html>\n"\
1619 "<head>\n"\
1620 "<meta name=\"Author\" content=\"Jean Le Feuvre - GPAC %s\">\n"\
1621 "<title>NdtListV%d.html</title>\n"\
1622 "</head>\n"\
1623 "<body>\n"\
1624 "<title>Node Coding Tables for BIFS Version %d group</title>\n"
1625 ,gf_gpac_version(), i+1, i+1);
1626
1627 for (j=0; j<nb_ndt; j++) {
1628 u32 nb_in_ndt = 0;
1629 char *ndt = gf_list_get(NDTs, j);
1630 for (k=0; k<nb_nodes; k++) {
1631 BNode *n = gf_list_get(nodes, k);
1632 if (n->version != i+1) continue;
1633 if (!IsNodeInTable(n, ndt)) continue;
1634 nb_in_ndt ++;
1635 }
1636
1637 if (!nb_in_ndt) continue;
1638
1639 fprintf(f, "<BR><a name=\"%s\">\n"\
1640 "<TABLE BORDER COLS=\"10\" CELLSPACING=\"0\" WIDTH=\"100%%\">\n"\
1641 "<TD COLSPAN=\"2\" width=\"200\"><B>%s</B></TD>\n"\
1642 "<TD COLSPAN=\"4\"><B>%u nodes</B></TD>\n", ndt, ndt, nb_in_ndt);
1643
1644 nb_bits = GetBitsCount(nb_in_ndt);
1645 fprintf(f, "<TR><TD>reserved</TD><TD><P align=CENTER>%s</TD><TD><P align=RIGHT> </TD><TD><P align=RIGHT> </TD><TD><P align=RIGHT> </TD><TD><P align=RIGHT> </TD></TR>\n", format_bit_string(szStr, 0, nb_bits));
1646
1647 idx = 1;
1648 for (k=0; k<nb_nodes; k++) {
1649 BNode *n = gf_list_get(nodes, k);
1650 if (n->version != i+1) continue;
1651 if (!IsNodeInTable(n, ndt)) continue;
1652
1653
1654 n->hasDef = n->hasIn = n->hasOut = n->hasDyn = 0;
1655 for (l=0; l<gf_list_count(n->Fields); l++) {
1656 BField *bf = gf_list_get(n->Fields, l);
1657 if (!strcmp(bf->type, "field") || !strcmp(bf->type, "exposedField")) {
1658 n->hasDef += 1;
1659 }
1660 if (!strcmp(bf->type, "eventIn") || !strcmp(bf->type, "exposedField")) {
1661 n->hasIn += 1;
1662 //check for anim
1663 if (bf->hasAnim) n->hasDyn += 1;
1664 }
1665 if (!strcmp(bf->type, "eventOut") || !strcmp(bf->type, "exposedField")) {
1666 n->hasOut += 1;
1667 }
1668 }
1669
1670 fprintf(f, "<TR><TD>%s</TD><TD><P align=CENTER>%s</TD><TD><P align=RIGHT>%d DEF bits</TD><TD><P align=RIGHT>%d IN bits</TD><TD><P align=RIGHT>%d OUT bits</TD><TD><P align=RIGHT>%d DYN bits</TD></TR>\n", n->name, format_bit_string(szStr, idx, nb_bits), get_nb_bits(n->hasDef), get_nb_bits(n->hasIn), get_nb_bits(n->hasOut), get_nb_bits(n->hasDyn));
1671 idx++;
1672 }
1673
1674 fprintf(f, "</TABLE>\n");
1675 }
1676 gf_fclose(f);
1677 }
1678
1679 }
1680
main(int argc,char ** argv)1681 int main (int argc, char **argv)
1682 {
1683 Bool generate_ndt = 0;
1684 char szTempFile[1024];
1685 FILE *nodes, *ndt_c, *ndt_h, *fskip;
1686 GF_List *BNodes, *NDTs;
1687 u32 i, j, nbVersion;
1688 BNode *n;
1689 BField *bf;
1690
1691 if (argc < 1) {
1692 PrintUsage();
1693 return 0;
1694 }
1695
1696 BNodes = gf_list_new();
1697 NDTs = gf_list_new();
1698
1699
1700
1701 fskip = NULL;
1702 if (argc>1) {
1703 i=1;
1704 if (!strcmp(argv[i], "-ndt")) {
1705 generate_ndt = 1;
1706 } else if (argv[i][0]=='-') {
1707 fskip = gf_fopen(argv[i+1], "rt");
1708 if (!fskip) {
1709 printf("file %s not found\n", argv[i+1]);
1710 return 0;
1711 }
1712 i+=2;
1713 }
1714 }
1715 nbVersion=1;
1716 while (1) {
1717 sprintf(szTempFile, "templates%u.txt", nbVersion);
1718 nodes = gf_fopen(szTempFile, "rt");
1719 if (!nodes) {
1720 sprintf(szTempFile, "template%u.txt", nbVersion);
1721 nodes = gf_fopen(szTempFile, "rt");
1722 }
1723 if (!nodes) break;
1724
1725 //all nodes are in the same list but we keep version info
1726 ParseTemplateFile(nodes, BNodes, NDTs, nbVersion);
1727
1728
1729 //special case for viewport: it is present in V1 but empty
1730 if (nbVersion==1) CheckInTable("SFViewportNode", NDTs);
1731 nbVersion++;
1732 gf_fclose(nodes);
1733 }
1734 nbVersion--;
1735 printf("BIFS tables parsed: %d versions\n", nbVersion);
1736
1737 if (generate_ndt) {
1738 generate_ndts(NDTs, BNodes, nbVersion);
1739 goto exit;
1740 }
1741
1742 if (fskip) {
1743 parse_profile(BNodes, fskip);
1744 gf_fclose(fskip);
1745 }
1746
1747 //write the nodes def
1748 WriteNodesFile(BNodes, NDTs, nbVersion);
1749 //write all nodes init stuff
1750 WriteNodeCode(BNodes);
1751
1752 //write all NDTs
1753 ndt_h = BeginFile("NDT", 0);
1754 ndt_c = BeginFile("NDT", 1);
1755
1756 fprintf(ndt_h, "#include <gpac/nodes_mpeg4.h>\n\n");
1757 fprintf(ndt_h, "\n\n#ifndef GPAC_DISABLE_BIFS\n");
1758
1759 fprintf(ndt_c, "\n\n#include <gpac/internal/bifs_tables.h>\n");
1760 fprintf(ndt_c, "\n\n#ifndef GPAC_DISABLE_BIFS\n");
1761
1762 //prepare the encoding file
1763 fprintf(ndt_h, "\n\nu32 ALL_GetNodeType(const u32 *table, const u32 count, u32 NodeTag, u32 Version);\n\n");
1764 fprintf(ndt_c, "\n\nu32 ALL_GetNodeType(const u32 *table, const u32 count, u32 NodeTag, u32 Version)\n{\n\tu32 i = 0;");
1765 fprintf(ndt_c, "\n\twhile (i<count) {\n\t\tif (table[i] == NodeTag) goto found;\n\t\ti++;\n\t}\n\treturn 0;\nfound:\n\tif (Version == 2) return i+2;\n\treturn i+1;\n}\n\n");
1766
1767 //write the NDT
1768 for (i=0; i<nbVersion; i++) {
1769 //write header
1770 WriteNDT_H(ndt_h, BNodes, NDTs, i+1);
1771 //write decoding code
1772 WriteNDT_Dec(ndt_c, BNodes, NDTs, i+1);
1773 //write encoding code
1774 WriteNDT_Enc(ndt_c, BNodes, NDTs, i+1);
1775 }
1776
1777
1778
1779 fprintf(ndt_c, "\n\nu32 gf_bifs_ndt_get_node_type(u32 NDT_Tag, u32 NodeType, u32 Version)\n{\n\tswitch (Version) {\n");
1780 for (i=0; i<nbVersion; i++) {
1781 fprintf(ndt_c, "\tcase GF_BIFS_V%d:\n\t\treturn NDT_V%d_GetNodeTag(NDT_Tag, NodeType);\n", i+1, i+1);
1782 }
1783 fprintf(ndt_c, "\tdefault:\n\t\treturn 0;\n\t}\n}");
1784
1785 fprintf(ndt_c, "\n\nu32 gf_bifs_get_ndt_bits(u32 NDT_Tag, u32 Version)\n{\n\tswitch (Version) {\n");
1786 for (i=0; i<nbVersion; i++) {
1787 fprintf(ndt_c, "\tcase GF_BIFS_V%d:\n\t\treturn NDT_V%d_GetNumBits(NDT_Tag);\n", i+1, i+1);
1788 }
1789 fprintf(ndt_c, "\tdefault:\n\t\treturn 0;\n\t}\n}");
1790
1791 fprintf(ndt_c, "\n\nu32 gf_bifs_get_node_type(u32 NDT_Tag, u32 NodeTag, u32 Version)\n{\n\tswitch (Version) {\n");
1792 for (i=0; i<nbVersion; i++) {
1793 fprintf(ndt_c, "\tcase GF_BIFS_V%d:\n\t\treturn NDT_V%d_GetNodeType(NDT_Tag, NodeTag);\n", i+1, i+1);
1794 }
1795 fprintf(ndt_c, "\tdefault:\n\t\treturn 0;\n\t}\n}");
1796
1797 fprintf(ndt_h, "\nu32 NDT_GetChildTable(u32 NodeTag);\n");
1798 fprintf(ndt_h, "\n\n");
1799
1800 //NDT checking
1801 fprintf(ndt_c, "u32 GetChildrenNDT(GF_Node *node)\n{\n\tif (!node) return 0;\n\tswitch (gf_node_get_tag(node)) {\n");
1802 for (i=0; i<gf_list_count(BNodes); i++) {
1803 n = gf_list_get(BNodes, i);
1804 if (n->skip_impl) continue;
1805 for (j=0; j<gf_list_count(n->Fields); j++) {
1806 bf = gf_list_get(n->Fields, j);
1807 if (!strcmp(bf->name, "children")) {
1808 fprintf(ndt_c, "\tcase TAG_MPEG4_%s:\n\t\treturn NDT_SF%s;\n", n->name, bf->familly+2);
1809 break;
1810 }
1811 }
1812 }
1813 fprintf(ndt_c, "\tdefault:\n\t\treturn 0;\n\t}\n}\n\n");
1814 fprintf(ndt_c, "\n\n#endif /*GPAC_DISABLE_BIFS*/\n\n");
1815
1816 fprintf(ndt_h, "\n\n#endif /*GPAC_DISABLE_BIFS*/\n\n");
1817 EndFile(ndt_h, "NDT", 0);
1818 EndFile(ndt_c, "", 1);
1819
1820
1821 exit:
1822 //free NDTs
1823 while (gf_list_count(NDTs)) {
1824 char *tmp = gf_list_get(NDTs, 0);
1825 gf_free(tmp);
1826 gf_list_rem(NDTs, 0);
1827 }
1828 gf_list_del(NDTs);
1829 //free nodes
1830 while (gf_list_count(BNodes)) {
1831 n = gf_list_get(BNodes, 0);
1832 gf_list_rem(BNodes, 0);
1833 while (gf_list_count(n->NDT)) {
1834 char *tmp = gf_list_get(n->NDT, 0);
1835 gf_free(tmp);
1836 gf_list_rem(n->NDT, 0);
1837 }
1838 gf_list_del(n->NDT);
1839 while (gf_list_count(n->Fields)) {
1840 bf = gf_list_get(n->Fields, 0);
1841 gf_free(bf);
1842 gf_list_rem(n->Fields, 0);
1843 }
1844 gf_list_del(n->Fields);
1845 gf_free(n);
1846 }
1847 gf_list_del(BNodes);
1848
1849 return 0;
1850 }
1851
1852