Coverage Report

Created: 2026-10-08 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpac/src/odf/odf_parse.c
Line
Count
Source
1
/*
2
 *      GPAC - Multimedia Framework C SDK
3
 *
4
 *      Authors: Jean Le Feuvre
5
 *      Copyright (c) Telecom ParisTech 2000-2026
6
 *          All rights reserved
7
 *
8
 *  This file is part of GPAC / MPEG-4 ObjectDescriptor 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
27
#include <gpac/internal/odf_dev.h>
28
#include <gpac/token.h>
29
#include <gpac/constants.h>
30
/*for import flags*/
31
#include <gpac/media_tools.h>
32
33
34
/* to complete...*/
35
36
GF_ODF_FieldType gf_odf_get_field_type(GF_Descriptor *desc, char *fieldName)
37
0
{
38
0
  switch (desc->tag) {
39
0
  case GF_ODF_IOD_TAG:
40
0
  case GF_ODF_OD_TAG:
41
0
    if (!stricmp(fieldName, "esDescr")) return GF_ODF_FT_OD_LIST;
42
0
    else if (!stricmp(fieldName, "ociDescr")) return GF_ODF_FT_OD_LIST;
43
0
    else if (!stricmp(fieldName, "ipmpDescrPtr")) return GF_ODF_FT_OD_LIST;
44
0
    else if (!stricmp(fieldName, "ipmpDescr")) return GF_ODF_FT_OD_LIST;
45
0
    else if (!stricmp(fieldName, "extDescr")) return GF_ODF_FT_OD_LIST;
46
0
    else if (!stricmp(fieldName, "toolListDescr")) return GF_ODF_FT_OD;
47
0
    return 0;
48
0
  case GF_ODF_DCD_TAG:
49
0
    if (!stricmp(fieldName, "decSpecificInfo")) return GF_ODF_FT_OD;
50
0
    if (!stricmp(fieldName, "profileLevelIndicationIndexDescr")) return GF_ODF_FT_OD_LIST;
51
0
    return 0;
52
0
  case GF_ODF_ESD_TAG:
53
0
    if (!stricmp(fieldName, "decConfigDescr")) return GF_ODF_FT_OD;
54
0
    if (!stricmp(fieldName, "muxInfo")) return GF_ODF_FT_OD;
55
0
    if (!stricmp(fieldName, "StreamSource")) return GF_ODF_FT_OD;
56
0
    if (!stricmp(fieldName, "slConfigDescr")) return GF_ODF_FT_OD;
57
0
    if (!stricmp(fieldName, "ipiPtr")) return GF_ODF_FT_OD;
58
0
    if (!stricmp(fieldName, "qosDescr")) return GF_ODF_FT_OD;
59
0
    if (!stricmp(fieldName, "regDescr")) return GF_ODF_FT_OD;
60
0
    if (!stricmp(fieldName, "langDescr")) return GF_ODF_FT_OD;
61
0
    if (!stricmp(fieldName, "ipIDS")) return GF_ODF_FT_OD_LIST;
62
0
    if (!stricmp(fieldName, "ipmpDescrPtr")) return GF_ODF_FT_OD_LIST;
63
0
    if (!stricmp(fieldName, "extDescr")) return GF_ODF_FT_OD_LIST;
64
0
    return 0;
65
0
  case GF_ODF_TEXT_CFG_TAG:
66
0
    if (!stricmp(fieldName, "SampleDescriptions")) return GF_ODF_FT_OD_LIST;
67
0
    return 0;
68
0
  case GF_ODF_IPMP_TAG:
69
0
    if (!stricmp(fieldName, "IPMPX_Data")) return GF_ODF_FT_IPMPX_LIST;
70
0
    return 0;
71
0
  case GF_ODF_IPMP_TL_TAG:
72
0
    if (!stricmp(fieldName, "ipmpTool")) return GF_ODF_FT_OD_LIST;
73
0
    return 0;
74
0
  case GF_ODF_IPMP_TOOL_TAG:
75
0
    if (!stricmp(fieldName, "toolParamDesc")) return GF_ODF_FT_IPMPX;
76
0
    return 0;
77
0
  case GF_ODF_BIFS_CFG_TAG:
78
0
    if (!stricmp(fieldName, "elementaryMask")) return GF_ODF_FT_OD_LIST;
79
0
    return 0;
80
0
  }
81
0
  return 0;
82
0
}
83
84
u32 gf_odf_get_tag_by_name(char *descName)
85
0
{
86
0
  if (!stricmp(descName, "ObjectDescriptor")) return GF_ODF_OD_TAG;
87
0
  if (!stricmp(descName, "InitialObjectDescriptor")) return GF_ODF_IOD_TAG;
88
0
  if (!stricmp(descName, "ES_Descriptor")) return GF_ODF_ESD_TAG;
89
0
  if (!stricmp(descName, "DecoderConfigDescriptor")) return GF_ODF_DCD_TAG;
90
0
  if (!stricmp(descName, "DecoderSpecificInfo")) return GF_ODF_DSI_TAG;
91
0
  if (!stricmp(descName, "DecoderSpecificInfoString")) return GF_ODF_DSI_TAG;
92
0
  if (!stricmp(descName, "SLConfigDescriptor")) return GF_ODF_SLC_TAG;
93
0
  if (!stricmp(descName, "SegmentDescriptor")) return GF_ODF_SEGMENT_TAG;
94
0
  if (!stricmp(descName, "MuxInfo")) return GF_ODF_MUXINFO_TAG;
95
0
  if (!stricmp(descName, "StreamSource")) return GF_ODF_MUXINFO_TAG;
96
0
  if (!stricmp(descName, "BIFSConfig") || !stricmp(descName, "BIFSv2Config")) return GF_ODF_BIFS_CFG_TAG;
97
0
  if (!stricmp(descName, "ElementaryMask")) return GF_ODF_ELEM_MASK_TAG;
98
0
  if (!stricmp(descName, "TextConfig")) return GF_ODF_TEXT_CFG_TAG;
99
0
  if (!stricmp(descName, "TextSampleDescriptor")) return GF_ODF_TX3G_TAG;
100
0
  if (!stricmp(descName, "UIConfig")) return GF_ODF_UI_CFG_TAG;
101
0
  if (!stricmp(descName, "ES_ID_Ref")) return GF_ODF_ESD_REF_TAG;
102
0
  if (!stricmp(descName, "ES_ID_Inc")) return GF_ODF_ESD_INC_TAG;
103
0
  if (!stricmp(descName, "AuxiliaryVideoData")) return GF_ODF_AUX_VIDEO_DATA;
104
0
  if (!stricmp(descName, "DefaultDescriptor")) return GF_ODF_DSI_TAG;
105
0
  if (!stricmp(descName, "LanguageDescriptor")) return GF_ODF_LANG_TAG;
106
0
  if (!stricmp(descName, "GPACLanguage")) return GF_ODF_GPAC_LANG;
107
108
#ifndef GPAC_MINIMAL_ODF
109
  if (!stricmp(descName, "MediaTimeDescriptor")) return GF_ODF_MEDIATIME_TAG;
110
  if (!stricmp(descName, "ContentIdentification")) return GF_ODF_CI_TAG;
111
  if (!stricmp(descName, "SuppContentIdentification")) return GF_ODF_SCI_TAG;
112
  if (!stricmp(descName, "IPIPtr")) return GF_ODF_IPI_PTR_TAG;
113
  if (!stricmp(descName, "IPMP_DescriptorPointer")) return GF_ODF_IPMP_PTR_TAG;
114
  if (!stricmp(descName, "IPMP_Descriptor")) return GF_ODF_IPMP_TAG;
115
  if (!stricmp(descName, "IPMP_ToolListDescriptor")) return GF_ODF_IPMP_TL_TAG;
116
  if (!stricmp(descName, "IPMP_Tool")) return GF_ODF_IPMP_TOOL_TAG;
117
  if (!stricmp(descName, "QoS")) return GF_ODF_QOS_TAG;
118
  if (!stricmp(descName, "RegistrationDescriptor")) return GF_ODF_REG_TAG;
119
  if (!stricmp(descName, "ExtensionPL")) return GF_ODF_EXT_PL_TAG;
120
  if (!stricmp(descName, "PL_IndicationIndex")) return GF_ODF_PL_IDX_TAG;
121
  if (!stricmp(descName, "ContentClassification")) return GF_ODF_CC_TAG;
122
  if (!stricmp(descName, "KeyWordDescriptor")) return GF_ODF_KW_TAG;
123
  if (!stricmp(descName, "RatingDescriptor")) return GF_ODF_RATING_TAG;
124
  if (!stricmp(descName, "ShortTextualDescriptor")) return GF_ODF_SHORT_TEXT_TAG;
125
  if (!stricmp(descName, "ExpandedTextualDescriptor")) return GF_ODF_TEXT_TAG;
126
  if (!stricmp(descName, "ContentCreatorName")) return GF_ODF_CC_NAME_TAG;
127
  if (!stricmp(descName, "ContentCreationDate")) return GF_ODF_CC_DATE_TAG;
128
  if (!stricmp(descName, "OCI_CreatorName")) return GF_ODF_OCI_NAME_TAG;
129
  if (!stricmp(descName, "OCI_CreationDate")) return GF_ODF_OCI_DATE_TAG;
130
  if (!stricmp(descName, "SmpteCameraPosition")) return GF_ODF_SMPTE_TAG;
131
#endif /*GPAC_MINIMAL_ODF*/
132
0
  return 0;
133
0
}
134
135
#include <gpac/internal/odf_parse_common.h>
136
137
void OD_ParseBinData(u8 *val, u8 **out_data, u32 *out_data_size)
138
0
{
139
0
  u32 i, c;
140
0
  char s[3];
141
0
  u32 len = (u32) strlen(val) / 3;
142
0
  if (*out_data) gf_free(*out_data);
143
0
  *out_data_size = len;
144
0
  *out_data = gf_malloc(sizeof(char) * len);
145
0
  s[2] = 0;
146
0
  for (i=0; i<len; i++) {
147
0
    s[0] = val[3*i+1];
148
0
    s[1] = val[3*i+2];
149
0
    sscanf(s, "%02X", &c);
150
0
    (*out_data)[i] = (unsigned char) c;
151
0
  }
152
0
}
153
154
GF_Err gf_odf_set_field(GF_Descriptor *desc, char *fieldName, char *val)
155
0
{
156
#ifndef GPAC_MINIMAL_ODF
157
  Bool OD_ParseUIConfig(u8 *val, u8 **out_data, u32 *out_data_size);
158
#endif
159
0
  u32 ret = 0;
160
0
  if (!fieldName || !val) return GF_BAD_PARAM;
161
0
  if (!stricmp(val, "auto")) return GF_OK;
162
0
  else if (!stricmp(val, "unspecified")) return GF_OK;
163
164
0
  switch (desc->tag) {
165
0
  case GF_ODF_IOD_TAG:
166
0
  {
167
0
    GF_InitialObjectDescriptor *iod = (GF_InitialObjectDescriptor *)desc;
168
0
    if (!stricmp(fieldName, "objectDescriptorID") || !stricmp(fieldName, "binaryID")) ret += sscanf(val, "%hu", &iod->objectDescriptorID);
169
0
    else if (!stricmp(fieldName, "URLString")) {
170
0
      iod->URLString = gf_strdup(val);
171
0
      ret = 1;
172
0
    }
173
0
    else if (!stricmp(fieldName, "includeInlineProfileLevelFlag")) {
174
0
      GET_BOOL(iod->inlineProfileFlag)
175
0
      if (!ret) {
176
0
        iod->inlineProfileFlag = 0;
177
0
        ret = 1;
178
0
      }
179
0
    }
180
0
    else if (!stricmp(fieldName, "ODProfileLevelIndication")) {
181
0
      GET_U8(iod->OD_profileAndLevel)
182
0
      if (!ret) {
183
0
        iod->OD_profileAndLevel = 0xFE;
184
0
        ret = 1;
185
0
      }
186
0
    }
187
0
    else if (!stricmp(fieldName, "sceneProfileLevelIndication")) {
188
0
      GET_U8(iod->scene_profileAndLevel)
189
0
      if (!ret) {
190
0
        iod->scene_profileAndLevel = 0xFE;
191
0
        ret = 1;
192
0
      }
193
0
    }
194
0
    else if (!stricmp(fieldName, "audioProfileLevelIndication")) {
195
0
      GET_U8(iod->audio_profileAndLevel)
196
0
      if (!ret) {
197
0
        iod->audio_profileAndLevel = 0xFE;
198
0
        ret = 1;
199
0
      }
200
0
    }
201
0
    else if (!stricmp(fieldName, "visualProfileLevelIndication")) {
202
0
      GET_U8(iod->visual_profileAndLevel)
203
0
      if (!ret) {
204
0
        iod->visual_profileAndLevel = 0xFE;
205
0
        ret = 1;
206
0
      }
207
0
    }
208
0
    else if (!stricmp(fieldName, "graphicsProfileLevelIndication")) {
209
0
      GET_U8(iod->graphics_profileAndLevel)
210
0
      if (!ret) {
211
0
        iod->graphics_profileAndLevel = 0xFE;
212
0
        ret = 1;
213
0
      }
214
0
    }
215
0
  }
216
0
  break;
217
0
  case GF_ODF_OD_TAG:
218
0
  {
219
0
    GF_ObjectDescriptor *od = (GF_ObjectDescriptor *) desc;
220
0
    if (!stricmp(fieldName, "objectDescriptorID") || !stricmp(fieldName, "binaryID")) ret += sscanf(val, "%hu", &od->objectDescriptorID);
221
0
    else if (!stricmp(fieldName, "URLString")) {
222
0
      od->URLString = gf_strdup(val);
223
0
      ret = 1;
224
0
    }
225
0
  }
226
0
  break;
227
0
  case GF_ODF_DCD_TAG:
228
0
  {
229
0
    GF_DecoderConfig *dcd = (GF_DecoderConfig *)desc;
230
0
    if (!stricmp(fieldName, "objectTypeIndication")) {
231
0
      GET_U8(dcd->objectTypeIndication)
232
      /*XMT may use string*/
233
0
      if (!ret) {
234
0
        if (!stricmp(val, "MPEG4Systems1")) {
235
0
          dcd->objectTypeIndication = GF_CODECID_OD_V1;
236
0
          ret = 1;
237
0
        }
238
0
        else if (!stricmp(val, "MPEG4Systems2")) {
239
0
          dcd->objectTypeIndication = GF_CODECID_BIFS_V2;
240
0
          ret = 1;
241
0
        }
242
0
        else if (!stricmp(val, "MPEG4Visual")) {
243
0
          dcd->objectTypeIndication = GF_CODECID_MPEG4_PART2;
244
0
          ret = 1;
245
0
        }
246
0
        else if (!stricmp(val, "MPEG4Audio")) {
247
0
          dcd->objectTypeIndication = GF_CODECID_AAC_MPEG4;
248
0
          ret = 1;
249
0
        }
250
0
        else if (!stricmp(val, "MPEG2VisualSimple")) {
251
0
          dcd->objectTypeIndication = GF_CODECID_MPEG2_SIMPLE;
252
0
          ret = 1;
253
0
        }
254
0
        else if (!stricmp(val, "MPEG2VisualMain")) {
255
0
          dcd->objectTypeIndication = GF_CODECID_MPEG2_MAIN;
256
0
          ret = 1;
257
0
        }
258
0
        else if (!stricmp(val, "MPEG2VisualSNR")) {
259
0
          dcd->objectTypeIndication = GF_CODECID_MPEG2_SNR;
260
0
          ret = 1;
261
0
        }
262
0
        else if (!stricmp(val, "MPEG2VisualSpatial")) {
263
0
          dcd->objectTypeIndication = GF_CODECID_MPEG2_SPATIAL;
264
0
          ret = 1;
265
0
        }
266
0
        else if (!stricmp(val, "MPEG2VisualHigh")) {
267
0
          dcd->objectTypeIndication = GF_CODECID_MPEG2_HIGH;
268
0
          ret = 1;
269
0
        }
270
0
        else if (!stricmp(val, "MPEG2Visual422")) {
271
0
          dcd->objectTypeIndication = GF_CODECID_MPEG2_422;
272
0
          ret = 1;
273
0
        }
274
0
        else if (!stricmp(val, "MPEG2AudioMain")) {
275
0
          dcd->objectTypeIndication = GF_CODECID_AAC_MPEG2_MP;
276
0
          ret = 1;
277
0
        }
278
0
        else if (!stricmp(val, "MPEG2AudioLowComplexity")) {
279
0
          dcd->objectTypeIndication = GF_CODECID_AAC_MPEG2_LCP;
280
0
          ret = 1;
281
0
        }
282
0
        else if (!stricmp(val, "MPEG2AudioScaleableSamplingRate")) {
283
0
          dcd->objectTypeIndication = GF_CODECID_AAC_MPEG2_SSRP;
284
0
          ret = 1;
285
0
        }
286
0
        else if (!stricmp(val, "MPEG2AudioPart3")) {
287
0
          dcd->objectTypeIndication = GF_CODECID_MPEG2_PART3;
288
0
          ret = 1;
289
0
        }
290
0
        else if (!stricmp(val, "MPEG1Visual")) {
291
0
          dcd->objectTypeIndication = GF_CODECID_MPEG1;
292
0
          ret = 1;
293
0
        }
294
0
        else if (!stricmp(val, "MPEG1Audio")) {
295
0
          dcd->objectTypeIndication = GF_CODECID_MPEG_AUDIO;
296
0
          ret = 1;
297
0
        }
298
0
        else if (!stricmp(val, "JPEG")) {
299
0
          dcd->objectTypeIndication = GF_CODECID_JPEG;
300
0
          ret = 1;
301
0
        }
302
0
        else if (!stricmp(val, "PNG")) {
303
0
          dcd->objectTypeIndication = GF_CODECID_PNG;
304
0
          ret = 1;
305
0
        }
306
0
      }
307
0
    }
308
0
    else if (!stricmp(fieldName, "streamType")) {
309
0
      GET_U8(dcd->streamType)
310
      /*XMT may use string*/
311
0
      if (!ret) {
312
0
        dcd->streamType = gf_stream_type_by_name(val);
313
0
        if (dcd->streamType != GF_STREAM_UNKNOWN)
314
0
          ret = 1;
315
0
      }
316
0
    }
317
0
    else if (!stricmp(fieldName, "upStream")) {
318
0
      GET_BOOL(dcd->upstream)
319
0
    }
320
0
    else if (!stricmp(fieldName, "bufferSizeDB")) ret += sscanf(val, "%u", &dcd->bufferSizeDB);
321
0
    else if (!stricmp(fieldName, "maxBitRate")) ret += sscanf(val, "%u", &dcd->maxBitrate);
322
0
    else if (!stricmp(fieldName, "avgBitRate")) ret += sscanf(val, "%u", &dcd->avgBitrate);
323
0
  }
324
0
  break;
325
0
  case GF_ODF_ESD_TAG:
326
0
  {
327
0
    GF_ESD *esd = (GF_ESD *)desc;
328
0
    if (!stricmp(fieldName, "ES_ID") || !stricmp(fieldName, "binaryID")) {
329
0
      ret += sscanf(val, "%hu", &esd->ESID);
330
0
    }
331
0
    else if (!stricmp(fieldName, "streamPriority")) GET_U8(esd->streamPriority)
332
0
    else if (!stricmp(fieldName, "dependsOn_ES_ID") || !stricmp(fieldName, "dependsOnESID")) ret += sscanf(val, "%hu", &esd->dependsOnESID);
333
0
    else if (!stricmp(fieldName, "OCR_ES_ID")) ret += sscanf(val, "%hu", &esd->OCRESID);
334
0
    else if (!stricmp(fieldName, "URLstring")) {
335
0
      esd->URLString = gf_strdup(val);
336
0
      ret = 1;
337
0
    }
338
    /*ignore*/
339
0
    else if (!stricmp(fieldName, "streamDependenceFlag")
340
0
       || !stricmp(fieldName, "URL_Flag")
341
0
       || !stricmp(fieldName, "OCRstreamFlag")
342
0
    )
343
0
      ret = 1;
344
0
  }
345
0
  break;
346
0
  case GF_ODF_SLC_TAG:
347
0
  {
348
0
    GF_SLConfig *slc = (GF_SLConfig*)desc;
349
0
    if (!stricmp(fieldName, "predefined")) GET_U8(slc->predefined)
350
0
    else if (!stricmp(fieldName, "useAccessUnitStartFlag")) GET_BOOL(slc->useAccessUnitStartFlag)
351
0
    else if (!stricmp(fieldName, "useAccessUnitEndFlag")) GET_BOOL(slc->useAccessUnitEndFlag)
352
0
    else if (!stricmp(fieldName, "useRandomAccessPointFlag")) GET_BOOL(slc->useRandomAccessPointFlag)
353
0
    else if (!stricmp(fieldName, "hasRandomAccessUnitsOnlyFlag") || !stricmp(fieldName, "useRandomAccessUnitsOnlyFlag")) GET_BOOL(slc->hasRandomAccessUnitsOnlyFlag)
354
0
    else if (!stricmp(fieldName, "usePaddingFlag")) GET_BOOL(slc->usePaddingFlag)
355
0
    else if (!stricmp(fieldName, "useTimeStampsFlag")) GET_BOOL(slc->useTimestampsFlag)
356
0
    else if (!stricmp(fieldName, "useIdleFlag")) GET_BOOL(slc->useIdleFlag)
357
0
    else if (!stricmp(fieldName, "timeStampResolution")) ret += sscanf(val, "%u", &slc->timestampResolution);
358
0
    else if (!stricmp(fieldName, "OCRResolution")) ret += sscanf(val, "%u", &slc->OCRResolution);
359
0
    else if (!stricmp(fieldName, "timeStampLength")) GET_U8(slc->timestampLength)
360
0
    else if (!stricmp(fieldName, "OCRLength")) GET_U8(slc->OCRLength)
361
0
    else if (!stricmp(fieldName, "AU_Length")) GET_U8(slc->AULength)
362
0
    else if (!stricmp(fieldName, "instantBitrateLength")) GET_U8(slc->instantBitrateLength)
363
0
    else if (!stricmp(fieldName, "degradationPriorityLength")) GET_U8(slc->degradationPriorityLength)
364
0
    else if (!stricmp(fieldName, "AU_seqNumLength")) GET_U8(slc->AUSeqNumLength)
365
0
    else if (!stricmp(fieldName, "packetSeqNumLength")) GET_U8(slc->packetSeqNumLength)
366
0
    else if (!stricmp(fieldName, "timeScale")) ret += sscanf(val, "%u", &slc->timeScale);
367
0
    else if (!stricmp(fieldName, "accessUnitDuration")) ret += sscanf(val, "%hu", &slc->AUDuration);
368
0
    else if (!stricmp(fieldName, "compositionUnitDuration")) ret += sscanf(val, "%hu", &slc->CUDuration);
369
0
    else if (!stricmp(fieldName, "startDecodingTimeStamp")) GET_U64(slc->startDTS)
370
0
    else if (!stricmp(fieldName, "startCompositionTimeStamp"))  GET_U64(slc->startCTS)
371
0
    else if (!stricmp(fieldName, "durationFlag")) ret = 1;
372
0
  }
373
0
  break;
374
0
  case GF_ODF_ELEM_MASK_TAG:
375
0
  {
376
0
    GF_ElementaryMask* em = (GF_ElementaryMask*)desc;
377
0
    if (!stricmp(fieldName, "atNode")) {
378
0
      GET_U32(em->node_id);
379
0
      if (!ret || !em->node_id) em->node_name = gf_strdup(val);
380
0
      ret = 1;
381
0
    }
382
0
    else if (!stricmp(fieldName, "numDynFields")) ret = 1;
383
0
  }
384
0
  break;
385
0
  case GF_ODF_BIFS_CFG_TAG:
386
0
  {
387
0
    GF_BIFSConfig *bcd = (GF_BIFSConfig*)desc;
388
0
    if (!stricmp(val, "auto")) return GF_OK;
389
0
    if (!stricmp(fieldName, "nodeIDbits")) ret += sscanf(val, "%hu", &bcd->nodeIDbits);
390
0
    else if (!stricmp(fieldName, "routeIDbits")) ret += sscanf(val, "%hu", &bcd->routeIDbits);
391
0
    else if (!stricmp(fieldName, "protoIDbits")) ret += sscanf(val, "%hu", &bcd->protoIDbits);
392
0
    else if (!stricmp(fieldName, "isCommandStream")) {
393
0
      /*GET_BOOL(bcd->isCommandStream)*/ ret = 1;
394
0
    }
395
0
    else if (!stricmp(fieldName, "pixelMetric") || !stricmp(fieldName, "pixelMetrics")) GET_BOOL(bcd->pixelMetrics)
396
0
    else if (!stricmp(fieldName, "pixelWidth")) ret += sscanf(val, "%hu", &bcd->pixelWidth);
397
0
    else if (!stricmp(fieldName, "pixelHeight")) ret += sscanf(val, "%hu", &bcd->pixelHeight);
398
0
    else if (!stricmp(fieldName, "use3DMeshCoding")) ret = 1;
399
0
    else if (!stricmp(fieldName, "usePredictiveMFField")) ret = 1;
400
0
    else if (!stricmp(fieldName, "randomAccess")) GET_BOOL(bcd->randomAccess)
401
0
    else if (!stricmp(fieldName, "useNames")) GET_BOOL(bcd->useNames)
402
0
  }
403
0
  break;
404
0
  case GF_ODF_MUXINFO_TAG:
405
0
  {
406
0
    GF_MuxInfo *mi = (GF_MuxInfo *)desc;
407
0
    if (!stricmp(fieldName, "fileName") || !stricmp(fieldName, "url")) GET_STRING(mi->file_name)
408
0
    else if (!stricmp(fieldName, "streamFormat")) GET_STRING(mi->streamFormat)
409
0
    else if (!stricmp(fieldName, "GroupID")) ret += sscanf(val, "%u", &mi->GroupID);
410
0
    else if (!stricmp(fieldName, "startTime")) ret += sscanf(val, "%d", &mi->startTime);
411
0
    else if (!stricmp(fieldName, "duration")) ret += sscanf(val, "%u", &mi->duration);
412
0
    else if (!stricmp(fieldName, "carouselPeriod")) {
413
0
      ret += sscanf(val, "%u", &mi->carousel_period_plus_one);
414
0
      mi->carousel_period_plus_one += 1;
415
0
    }
416
0
    else if (!stricmp(fieldName, "aggregateOnESID")) ret += sscanf(val, "%hu", &mi->aggregate_on_esid);
417
418
0
#ifndef GPAC_DISABLE_MEDIA_IMPORT
419
0
    else if (!stricmp(fieldName, "compactSize"))
420
0
    {
421
0
      ret = 1;
422
0
      if (!stricmp(val, "true") || !stricmp(val, "1")) mi->import_flags |= GF_IMPORT_USE_COMPACT_SIZE;
423
0
    }
424
0
    else if (!stricmp(fieldName, "useDataReference")) {
425
0
      ret = 1;
426
0
      if (!stricmp(val, "true") || !stricmp(val, "1")) mi->import_flags |= GF_IMPORT_USE_DATAREF;
427
0
    }
428
0
    else if (!stricmp(fieldName, "noFrameDrop")) {
429
0
      ret = 1;
430
0
      if (!stricmp(val, "true") || !stricmp(val, "1")) mi->import_flags |= GF_IMPORT_NO_FRAME_DROP;
431
0
    }
432
0
    else if (!stricmp(fieldName, "SBR_Type")) {
433
0
      ret = 1;
434
0
      if (!stricmp(val, "implicit") || !stricmp(val, "1")) mi->import_flags |= GF_IMPORT_SBR_IMPLICIT;
435
0
      else if (!stricmp(val, "explicit") || !stricmp(val, "2")) mi->import_flags |= GF_IMPORT_SBR_EXPLICIT;
436
0
    }
437
0
#endif /*GPAC_DISABLE_MEDIA_IMPORT*/
438
0
    else if (!stricmp(fieldName, "textNode")) GET_STRING(mi->textNode)
439
0
    else if (!stricmp(fieldName, "fontNode")) GET_STRING(mi->fontNode)
440
0
    else if (!stricmp(fieldName, "frameRate")) {
441
0
      ret = 1;
442
0
      mi->frame_rate = atof(val);
443
0
    }
444
0
  }
445
0
  break;
446
0
  case GF_ODF_DSI_TAG:
447
0
  {
448
0
    GF_DefaultDescriptor *dsi = (GF_DefaultDescriptor*)desc;
449
0
    if (!stricmp(fieldName, "info")) {
450
      /*only parse true hexa strings*/
451
0
      if (val[0] == '%') {
452
0
        OD_ParseBinData(val, &dsi->data, &dsi->dataLength);
453
0
        ret = 1;
454
0
      } else if (!strnicmp(val, "file:", 5)) {
455
0
        if (gf_file_load_data(val+5, (u8 **) &dsi->data, &dsi->dataLength) == GF_OK)
456
0
          ret = 1;
457
0
      } else if (!strlen(val)) ret = 1;
458
0
    }
459
0
    if (!stricmp(fieldName, "src")) {
460
0
      u32 len = (u32) strlen("data:application/octet-string,");
461
0
      if (strnicmp(val, "data:application/octet-string,", len)) break;
462
0
      val += len;
463
      /*only parse true hexa strings*/
464
0
      if (val[0] == '%') {
465
0
        OD_ParseBinData(val, &dsi->data, &dsi->dataLength);
466
0
        ret = 1;
467
0
      } else if (!strnicmp(val, "file:", 5)) {
468
0
        if (gf_file_load_data(val+5, (u8 **) &dsi->data, &dsi->dataLength) == GF_OK)
469
0
          ret = 1;
470
0
      }
471
0
    }
472
0
  }
473
0
  break;
474
0
  case GF_ODF_SEGMENT_TAG:
475
0
  {
476
0
    GF_Segment *sd = (GF_Segment*)desc;
477
0
    if (!stricmp(fieldName, "start") || !stricmp(fieldName, "startTime")) GET_DOUBLE(sd->startTime)
478
0
    else if (!stricmp(fieldName, "duration")) GET_DOUBLE(sd->Duration)
479
0
    else if (!stricmp(fieldName, "name") || !stricmp(fieldName, "segmentName")) GET_STRING(sd->SegmentName)
480
0
  }
481
0
  break;
482
0
  case GF_ODF_UI_CFG_TAG:
483
0
  {
484
0
    GF_UIConfig *uic = (GF_UIConfig*)desc;
485
0
    if (!stricmp(fieldName, "deviceName")) GET_STRING(uic->deviceName)
486
0
    else if (!stricmp(fieldName, "termChar")) GET_U8(uic->termChar)
487
0
    else if (!stricmp(fieldName, "delChar")) GET_U8(uic->delChar)
488
0
    else if (!stricmp(fieldName, "uiData")) {
489
      /*only parse true hexa strings*/
490
0
      if (val[0] == '%') {
491
0
        OD_ParseBinData(val, &uic->ui_data, &uic->ui_data_length);
492
0
        ret = 1;
493
0
      } else if (!strnicmp(val, "file:", 5)) {
494
0
        if (gf_file_load_data(val+5, (u8 **) &uic->ui_data, &uic->ui_data_length)==GF_OK)
495
0
          ret = 1;
496
0
      } else {
497
#ifndef GPAC_MINIMAL_ODF
498
        ret = OD_ParseUIConfig(val, &uic->ui_data, &uic->ui_data_length);
499
#else
500
0
        ret= GF_FALSE;
501
0
#endif
502
0
      }
503
0
    }
504
0
  }
505
0
  break;
506
0
  case GF_ODF_ESD_INC_TAG:
507
0
  {
508
0
    GF_ES_ID_Inc *inc = (GF_ES_ID_Inc *)desc;
509
0
    if (!stricmp(fieldName, "trackID")) ret += sscanf(val, "%u", &inc->trackID);
510
0
  }
511
0
  break;
512
0
  case GF_ODF_ESD_REF_TAG:
513
0
  {
514
0
    GF_ES_ID_Ref *inc = (GF_ES_ID_Ref *)desc;
515
0
    if (!stricmp(fieldName, "trackID")) ret += sscanf(val, "%hu", &inc->trackRef);
516
0
  }
517
0
  break;
518
0
  case GF_ODF_TEXT_CFG_TAG:
519
0
  {
520
0
    GF_TextConfig *txt = (GF_TextConfig*)desc;
521
0
    if (!stricmp(fieldName, "3GPPBaseFormat")) GET_U8(txt->Base3GPPFormat)
522
0
    else if (!stricmp(fieldName, "MPEGExtendedFormat")) GET_U8(txt->MPEGExtendedFormat)
523
0
    else if (!stricmp(fieldName, "profileLevel")) GET_U8(txt->profileLevel)
524
0
    else if (!stricmp(fieldName, "durationClock") || !stricmp(fieldName, "timescale") ) GET_U32(txt->timescale)
525
0
    else if (!stricmp(fieldName, "layer")) GET_U32(txt->layer)
526
0
    else if (!stricmp(fieldName, "text_width")) GET_U32(txt->text_width)
527
0
    else if (!stricmp(fieldName, "text_height")) GET_U32(txt->text_height)
528
0
    else if (!stricmp(fieldName, "video_width")) {
529
0
      GET_U32(txt->video_width)
530
0
      txt->has_vid_info = GF_TRUE;
531
0
    }
532
0
    else if (!stricmp(fieldName, "video_height")) {
533
0
      GET_U32(txt->video_height)
534
0
      txt->has_vid_info = GF_TRUE;
535
0
    }
536
0
    else if (!stricmp(fieldName, "horizontal_offset")) {
537
0
      GET_S16(txt->horiz_offset)
538
0
      txt->has_vid_info = GF_TRUE;
539
0
    }
540
0
    else if (!stricmp(fieldName, "vertical_offset")) {
541
0
      GET_S32(txt->vert_offset)
542
0
      txt->has_vid_info = GF_TRUE;
543
0
    }
544
0
  }
545
0
  break;
546
0
  case GF_ODF_TX3G_TAG:
547
0
  {
548
0
    GF_TextSampleDescriptor *sd = (GF_TextSampleDescriptor*)desc;
549
0
    if (!stricmp(fieldName, "displayFlags")) GET_U32(sd->displayFlags)
550
0
    else if (!stricmp(fieldName, "horiz_justif")) GET_S32(sd->horiz_justif)
551
0
    else if (!stricmp(fieldName, "vert_justif")) GET_S32(sd->vert_justif)
552
0
    else if (!stricmp(fieldName, "back_color")) GET_S32(sd->back_color)
553
0
    else if (!stricmp(fieldName, "top")) GET_S32(sd->default_pos.top)
554
0
    else if (!stricmp(fieldName, "bottom")) GET_S32(sd->default_pos.bottom)
555
0
    else if (!stricmp(fieldName, "left")) GET_S32(sd->default_pos.left)
556
0
    else if (!stricmp(fieldName, "right")) GET_S32(sd->default_pos.right)
557
0
    else if (!stricmp(fieldName, "style_font_ID")) GET_S32(sd->default_style.fontID)
558
0
    else if (!stricmp(fieldName, "style_font_size")) GET_S32(sd->default_style.font_size)
559
0
    else if (!stricmp(fieldName, "style_text_color")) GET_U32(sd->default_style.text_color)
560
0
    else if (!stricmp(fieldName, "style_flags")) {
561
0
      char szStyles[1024];
562
0
      gf_strcpy(szStyles, val);
563
0
      strlwr(szStyles);
564
0
      if (strstr(szStyles, "bold")) sd->default_style.style_flags |= GF_TXT_STYLE_BOLD;
565
0
      if (strstr(szStyles, "italic")) sd->default_style.style_flags |= GF_TXT_STYLE_ITALIC;
566
0
      if (strstr(szStyles, "underlined")) sd->default_style.style_flags |= GF_TXT_STYLE_UNDERLINED;
567
0
      if (strstr(szStyles, "strikethrough")) sd->default_style.style_flags |= GF_TXT_STYLE_STRIKETHROUGH;
568
0
      ret = 1;
569
0
    }
570
0
    else if (!stricmp(fieldName, "fontID") || !stricmp(fieldName, "fontName")) {
571
      /*check if we need a new entry*/
572
0
      if (!sd->font_count) {
573
0
        sd->fonts = (GF_FontRecord*)gf_malloc(sizeof(GF_FontRecord));
574
0
        sd->font_count = 1;
575
0
        sd->fonts[0].fontID = 0;
576
0
        sd->fonts[0].fontName = NULL;
577
0
      } else {
578
0
        Bool realloc_fonts = GF_FALSE;
579
0
        if (!stricmp(fieldName, "fontID") && sd->fonts[sd->font_count-1].fontID) realloc_fonts = GF_TRUE;
580
0
        else if (!stricmp(fieldName, "fontName") && sd->fonts[sd->font_count-1].fontName) realloc_fonts = GF_TRUE;
581
0
        if (realloc_fonts) {
582
0
          sd->font_count += 1;
583
0
          sd->fonts = (GF_FontRecord*)gf_realloc(sd->fonts, sizeof(GF_FontRecord)*sd->font_count);
584
0
          sd->fonts[sd->font_count-1].fontID = 0;
585
0
          sd->fonts[sd->font_count-1].fontName = NULL;
586
0
        }
587
0
      }
588
0
      if (!stricmp(fieldName, "fontID")) GET_U32(sd->fonts[sd->font_count-1].fontID)
589
0
      if (!stricmp(fieldName, "fontName")) GET_STRING(sd->fonts[sd->font_count-1].fontName)
590
0
    }
591
0
  }
592
0
  break;
593
0
  case GF_ODF_IPMP_TAG:
594
0
  {
595
0
    GF_IPMP_Descriptor *ipmp = (GF_IPMP_Descriptor*)desc;
596
0
    if (!stricmp(fieldName, "IPMP_DescriptorID")) GET_U8(ipmp->IPMP_DescriptorID)
597
0
    else if (!stricmp(fieldName, "IPMPS_Type")) GET_U16(ipmp->IPMPS_Type)
598
0
    else if (!stricmp(fieldName, "IPMP_DescriptorIDEx")) GET_U16(ipmp->IPMP_DescriptorIDEx)
599
0
    else if (!stricmp(fieldName, "IPMP_ToolID")) {
600
0
      ret = 1;
601
0
      gf_bin128_parse(val, ipmp->IPMP_ToolID);
602
0
    }
603
0
    else if (!stricmp(fieldName, "controlPointCode")) GET_U8(ipmp->control_point)
604
0
    else if (!stricmp(fieldName, "sequenceCode")) GET_U8(ipmp->cp_sequence_code)
605
0
  }
606
0
  break;
607
0
  case GF_ODF_IPMP_PTR_TAG:
608
0
  {
609
0
    GF_IPMPPtr *ipmpd = (GF_IPMPPtr*)desc;
610
0
    if (!stricmp(fieldName, "IPMP_DescriptorID")) GET_U8(ipmpd->IPMP_DescriptorID)
611
0
    else if (!stricmp(fieldName, "IPMP_DescriptorIDEx"))  ret += sscanf(val, "%hu", &ipmpd->IPMP_DescriptorIDEx);
612
0
    else if (!stricmp(fieldName, "IPMP_ES_ID"))  ret += sscanf(val, "%hu", &ipmpd->IPMP_ES_ID);
613
0
  }
614
0
  break;
615
0
  case GF_ODF_LANG_TAG:
616
0
  case GF_ODF_GPAC_LANG:
617
0
  {
618
0
    GF_Language *ld = (GF_Language *)desc;
619
0
    if (!stricmp(fieldName, "languageCode")) {
620
0
      u32 li, l = (u32) strlen(val);
621
0
      ld->langCode = 0;
622
0
      for (li = 0; li < l; li++) {
623
        /* Warning: sensitive to big endian, little endian */
624
0
        ld->langCode |= (val[li] << (l-li-1)*8);
625
0
      }
626
0
      ret++;
627
0
    }
628
0
  }
629
0
  break;
630
0
  case GF_ODF_AUX_VIDEO_DATA:
631
0
  {
632
0
    GF_AuxVideoDescriptor *avd = (GF_AuxVideoDescriptor *)desc;
633
0
    if (!stricmp(fieldName, "aux_video_type"))  GET_U8(avd->aux_video_type)
634
0
    else if (!stricmp(fieldName, "position_offset_h"))  GET_U8(avd->position_offset_h)
635
0
    else if (!stricmp(fieldName, "position_offset_v"))  GET_U8(avd->position_offset_v)
636
0
    else if (!stricmp(fieldName, "knear"))  GET_U8(avd->knear)
637
0
    else if (!stricmp(fieldName, "kfar"))  GET_U8(avd->kfar)
638
0
    else if (!stricmp(fieldName, "parallax_zero"))  GET_U16(avd->parallax_zero)
639
0
    else if (!stricmp(fieldName, "parallax_scale"))  GET_U16(avd->parallax_scale)
640
0
    else if (!stricmp(fieldName, "dref"))  GET_U16(avd->dref)
641
0
    else if (!stricmp(fieldName, "wref"))  GET_U16(avd->wref)
642
0
  }
643
0
  break;
644
0
  case GF_ODF_IPMP_TOOL_TAG:
645
0
  {
646
0
    GF_IPMP_Tool *it = (GF_IPMP_Tool*)desc;
647
0
    if (!stricmp(fieldName, "IPMP_ToolID")) {
648
0
      ret = 1;
649
0
      gf_bin128_parse(val, it->IPMP_ToolID);
650
0
    }
651
0
    else if (!stricmp(fieldName, "ToolURL"))  GET_STRING(it->tool_url)
652
0
    }
653
0
  break;
654
0
  }
655
656
0
  return ret ? GF_OK : GF_BAD_PARAM;
657
0
}
658
659
#ifndef GPAC_MINIMAL_ODF
660
Bool OD_ParseUIConfig(u8 *val, u8 **out_data, u32 *out_data_size)
661
{
662
  GF_BitStream *bs;
663
  if (!strnicmp(val, "HTK:", 4)) {
664
    char szItem[100];
665
    s64 pos, bs_start, bs_cur;
666
    Bool has_word;
667
    u32 nb_phonems, nbWords = 0;
668
    bs_start = 0;
669
    nb_phonems = 0;
670
    bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
671
    /*we'll write the nb of words later on*/
672
    gf_bs_write_int(bs, 0, 8);
673
    has_word = GF_FALSE;
674
    /*parse all words*/
675
    val += 4;
676
    while (1) {
677
      pos = gf_token_get(val, 0, " ;", szItem, 100);
678
      if (pos>0) val += pos;
679
      if (!has_word) {
680
        has_word = GF_TRUE;
681
        nbWords++;
682
        nb_phonems = 0;
683
        bs_start = gf_bs_get_position(bs);
684
        /*nb phonems*/
685
        gf_bs_write_int(bs, 0, 8);
686
        gf_bs_write_data(bs, szItem, (u32) strlen(szItem));
687
        gf_bs_write_int(bs, 0, 8);
688
        continue;
689
      }
690
      if (pos>0) {
691
692
        nb_phonems ++;
693
        /*would be nicer with a phone book & use indexes*/
694
        if (!stricmp(szItem, "vcl")) {
695
          gf_bs_write_data(bs, "vc", 2);
696
        } else {
697
          gf_bs_write_data(bs, szItem, 2);
698
        }
699
700
        while (val[0] && (val[0]==' ')) val += 1;
701
      }
702
703
      if ((pos<0) || !val[0] || val[0]==';') {
704
        if (has_word) {
705
          has_word = GF_FALSE;
706
          bs_cur = gf_bs_get_position(bs);
707
          gf_bs_seek(bs, bs_start);
708
          gf_bs_write_int(bs, nb_phonems, 8);
709
          gf_bs_seek(bs, bs_cur);
710
        }
711
        if ((pos<0) || !val[0]) break;
712
        val += 1;
713
        while (val[0] && (val[0]==' ')) val += 1;
714
      }
715
    }
716
    if (nbWords) {
717
      bs_cur = gf_bs_get_position(bs);
718
      gf_bs_seek(bs, 0);
719
      gf_bs_write_int(bs, nbWords, 8);
720
      gf_bs_seek(bs, bs_cur);
721
      gf_bs_get_content(bs, out_data, out_data_size);
722
    }
723
    gf_bs_del(bs);
724
    return GF_TRUE;
725
  }
726
  return GF_FALSE;
727
}
728
#endif