Coverage Report

Created: 2024-02-11 06:48

/src/gpac/src/odf/odf_command.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *      GPAC - Multimedia Framework C SDK
3
 *
4
 *      Authors: Jean Le Feuvre
5
 *      Copyright (c) Telecom ParisTech 2000-2012
6
 *          All rights reserved
7
 *
8
 *  This file is part of GPAC / 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
29
30
GF_Err gf_odf_parse_command(GF_BitStream *bs, GF_ODCom **com, u32 *com_size)
31
0
{
32
0
  u32 val, size, sizeHeader;
33
0
  u8 tag;
34
0
  GF_Err err;
35
0
  GF_ODCom *newCom;
36
0
  if (!bs) return GF_BAD_PARAM;
37
38
0
  *com_size = 0;
39
40
  //tag
41
0
  tag = gf_bs_read_int(bs, 8);
42
0
  sizeHeader = 1;
43
44
  //size
45
0
  size = 0;
46
0
  do {
47
0
    val = gf_bs_read_int(bs, 8);
48
0
    sizeHeader++;
49
0
    size <<= 7;
50
0
    size |= val & 0x7F;
51
0
  } while ( val & 0x80 );
52
0
  *com_size = size;
53
54
0
  newCom = gf_odf_create_command(tag);
55
0
  if (! newCom) {
56
0
    *com = NULL;
57
0
    return GF_OUT_OF_MEM;
58
0
  }
59
60
0
  newCom->tag = tag;
61
62
0
  err = gf_odf_read_command(bs, newCom, *com_size);
63
  //little trick to handle lazy bitstreams that encode
64
  //SizeOfInstance on a fix number of bytes
65
  //This nb of bytes is added in Read methods
66
0
  *com_size += sizeHeader - gf_odf_size_field_size(*com_size);
67
0
  *com = newCom;
68
0
  if (err) {
69
0
    gf_odf_delete_command(newCom);
70
0
    *com = NULL;
71
0
  }
72
0
  return err;
73
0
}
74
75
#ifndef GPAC_MINIMAL_ODF
76
77
GF_ODCom *gf_odf_new_base_command()
78
{
79
  GF_BaseODCom *newCom = (GF_BaseODCom *) gf_malloc(sizeof(GF_BaseODCom));
80
  if (!newCom) return NULL;
81
  newCom->dataSize = 0;
82
  newCom->data = NULL;
83
  return (GF_ODCom *)newCom;
84
}
85
GF_Err gf_odf_del_base_command(GF_BaseODCom *bcRemove)
86
{
87
  if (! bcRemove) return GF_BAD_PARAM;
88
  if (bcRemove->data) gf_free(bcRemove->data);
89
  gf_free(bcRemove);
90
  return GF_OK;
91
}
92
93
GF_Err gf_odf_read_base_command(GF_BitStream *bs, GF_BaseODCom *bcRem, u32 gf_odf_size_command)
94
{
95
  if (! bcRem) return GF_BAD_PARAM;
96
97
  bcRem->dataSize = gf_odf_size_command;
98
  bcRem->data = (char *) gf_malloc(sizeof(char) * bcRem->dataSize);
99
  if (! bcRem->data) return GF_OUT_OF_MEM;
100
  gf_bs_read_data(bs, bcRem->data, bcRem->dataSize);
101
  return GF_OK;
102
}
103
GF_Err gf_odf_size_base_command(GF_BaseODCom *bcRem, u32 *outSize)
104
{
105
  if (!bcRem) return GF_BAD_PARAM;
106
  *outSize = bcRem->dataSize;
107
  return GF_OK;
108
}
109
GF_Err gf_odf_write_base_command(GF_BitStream *bs, GF_BaseODCom *bcRem)
110
{
111
  u32 size;
112
  GF_Err e;
113
  if (! bcRem) return GF_BAD_PARAM;
114
115
  e = gf_odf_size_base_command(bcRem, &size);
116
  if (e) return e;
117
  e = gf_odf_write_base_descriptor(bs, bcRem->tag, size);
118
  if (e) return e;
119
  gf_bs_write_data(bs, bcRem->data, bcRem->dataSize);
120
  return GF_OK;
121
}
122
#endif
123
124
GF_ODCom *gf_odf_new_od_remove()
125
0
{
126
0
  GF_ODRemove *newCom = (GF_ODRemove *) gf_malloc(sizeof(GF_ODRemove));
127
0
  if (!newCom) return NULL;
128
0
  newCom->NbODs = 0;
129
0
  newCom->OD_ID = NULL;
130
0
  newCom->tag = GF_ODF_OD_REMOVE_TAG;
131
0
  return (GF_ODCom *)newCom;
132
0
}
133
GF_Err gf_odf_del_od_remove(GF_ODRemove *ODRemove)
134
0
{
135
0
  if (! ODRemove) return GF_BAD_PARAM;
136
0
  if (ODRemove->OD_ID) gf_free(ODRemove->OD_ID);
137
0
  gf_free(ODRemove);
138
0
  return GF_OK;
139
0
}
140
GF_Err gf_odf_read_od_remove(GF_BitStream *bs, GF_ODRemove *odRem, u32 gf_odf_size_command)
141
0
{
142
0
  u32 i = 0, nbBits;
143
0
  if (! odRem) return GF_BAD_PARAM;
144
145
0
  odRem->NbODs = (u32 ) (gf_odf_size_command * 8) / 10;
146
0
  odRem->OD_ID = (u16 *) gf_malloc(sizeof(u16) * odRem->NbODs);
147
0
  if (! odRem->OD_ID) return GF_OUT_OF_MEM;
148
149
0
  for (i = 0; i < odRem->NbODs ; i++) {
150
0
    odRem->OD_ID[i] = gf_bs_read_int(bs, 10);
151
0
  }
152
0
  nbBits = odRem->NbODs * 10;
153
  //now we need to align !!!
154
0
  nbBits += gf_bs_align(bs);
155
0
  if (nbBits != (gf_odf_size_command * 8)) return GF_ODF_INVALID_COMMAND;
156
0
  return GF_OK;
157
0
}
158
159
GF_Err gf_odf_size_od_remove(GF_ODRemove *odRem, u32 *outSize)
160
0
{
161
0
  u32 size;
162
0
  if (!odRem) return GF_BAD_PARAM;
163
164
0
  size = 10 * odRem->NbODs;
165
0
  *outSize = size/8;
166
0
  if (*outSize * 8 != size) *outSize += 1;
167
0
  return GF_OK;
168
0
}
169
170
GF_Err gf_odf_write_od_remove(GF_BitStream *bs, GF_ODRemove *odRem)
171
0
{
172
0
  GF_Err e;
173
0
  u32 size, i;
174
0
  if (! odRem) return GF_BAD_PARAM;
175
176
0
  e = gf_odf_size_od_remove(odRem, &size);
177
0
  if (e) return e;
178
0
  e = gf_odf_write_base_descriptor(bs, odRem->tag, size);
179
0
  if (e) return e;
180
181
0
  for (i = 0; i < odRem->NbODs; i++) {
182
0
    gf_bs_write_int(bs, odRem->OD_ID[i], 10);
183
0
  }
184
  //OD commands are aligned
185
0
  gf_bs_align(bs);
186
0
  return GF_OK;
187
0
}
188
189
190
191
GF_ODCom *gf_odf_new_od_update()
192
0
{
193
0
  GF_ODUpdate *newCom = (GF_ODUpdate *) gf_malloc(sizeof(GF_ODUpdate));
194
0
  if (!newCom) return NULL;
195
196
0
  newCom->objectDescriptors = gf_list_new();
197
0
  if (! newCom->objectDescriptors) {
198
0
    gf_free(newCom);
199
0
    return NULL;
200
0
  }
201
0
  newCom->tag = GF_ODF_OD_UPDATE_TAG;
202
0
  return (GF_ODCom *)newCom;
203
0
}
204
205
GF_Err gf_odf_del_od_update(GF_ODUpdate *ODUpdate)
206
0
{
207
0
  GF_Err e;
208
0
  if (! ODUpdate) return GF_BAD_PARAM;
209
0
  while (gf_list_count(ODUpdate->objectDescriptors)) {
210
0
    GF_Descriptor *tmp = (GF_Descriptor*)gf_list_get(ODUpdate->objectDescriptors, 0);
211
0
    e = gf_odf_delete_descriptor(tmp);
212
0
    if (e) return e;
213
0
    e = gf_list_rem(ODUpdate->objectDescriptors, 0);
214
0
    if (e) return e;
215
0
  }
216
0
  gf_list_del(ODUpdate->objectDescriptors);
217
0
  gf_free(ODUpdate);
218
0
  return GF_OK;
219
0
}
220
221
222
223
GF_Err AddToODUpdate(GF_ODUpdate *odUp, GF_Descriptor *desc)
224
0
{
225
0
  if (! odUp) return GF_BAD_PARAM;
226
0
  if (! desc) return GF_OK;
227
228
0
  switch (desc->tag) {
229
0
  case GF_ODF_OD_TAG:
230
0
  case GF_ODF_IOD_TAG:
231
0
  case GF_ODF_ISOM_IOD_TAG:
232
0
  case GF_ODF_ISOM_OD_TAG:
233
0
    return gf_list_add(odUp->objectDescriptors, desc);
234
235
0
  default:
236
0
    gf_odf_delete_descriptor(desc);
237
0
    return GF_OK;
238
0
  }
239
0
}
240
241
GF_Err gf_odf_read_od_update(GF_BitStream *bs, GF_ODUpdate *odUp, u32 gf_odf_size_command)
242
0
{
243
0
  GF_Descriptor *tmp;
244
0
  GF_Err e = GF_OK;
245
0
  u32 tmpSize = 0, nbBytes = 0;
246
0
  if (! odUp) return GF_BAD_PARAM;
247
248
0
  while (nbBytes < gf_odf_size_command) {
249
0
    e = gf_odf_parse_descriptor(bs, &tmp, &tmpSize);
250
0
    if (e) return e;
251
0
    e = AddToODUpdate(odUp, tmp);
252
0
    if (e) return e;
253
0
    nbBytes += tmpSize + gf_odf_size_field_size(tmpSize);
254
0
  }
255
  //OD commands are aligned
256
0
  gf_bs_align(bs);
257
0
  if (nbBytes != gf_odf_size_command) return GF_ODF_INVALID_COMMAND;
258
0
  return e;
259
0
}
260
GF_Err gf_odf_size_od_update(GF_ODUpdate *odUp, u32 *outSize)
261
0
{
262
0
  GF_Descriptor *tmp;
263
0
  u32 i, tmpSize;
264
0
  if (!odUp) return GF_BAD_PARAM;
265
266
0
  *outSize = 0;
267
0
  i=0;
268
0
  while ((tmp = (GF_Descriptor *)gf_list_enum(odUp->objectDescriptors, &i))) {
269
0
    gf_odf_size_descriptor(tmp, &tmpSize);
270
0
    *outSize += tmpSize + gf_odf_size_field_size(tmpSize);
271
0
  }
272
0
  return GF_OK;
273
0
}
274
GF_Err gf_odf_write_od_update(GF_BitStream *bs, GF_ODUpdate *odUp)
275
0
{
276
0
  GF_Err e;
277
0
  GF_Descriptor *tmp;
278
0
  u32 size, i;
279
0
  if (! odUp) return GF_BAD_PARAM;
280
281
0
  e = gf_odf_size_od_update(odUp, &size);
282
0
  if (e) return e;
283
0
  e = gf_odf_write_base_descriptor(bs, odUp->tag, size);
284
0
  if (e) return e;
285
286
0
  i=0;
287
0
  while ((tmp = (GF_Descriptor *)gf_list_enum(odUp->objectDescriptors, &i))) {
288
0
    e = gf_odf_write_descriptor(bs, tmp);
289
0
    if (e) return e;
290
0
  }
291
  //OD commands are aligned
292
0
  gf_bs_align(bs);
293
0
  return GF_OK;
294
0
}
295
296
297
GF_ODCom *gf_odf_new_esd_update()
298
0
{
299
0
  GF_ESDUpdate *newCom = (GF_ESDUpdate *) gf_malloc(sizeof(GF_ESDUpdate));
300
0
  if (!newCom) return NULL;
301
302
0
  newCom->ESDescriptors = gf_list_new();
303
0
  if (! newCom->ESDescriptors) {
304
0
    gf_free(newCom);
305
0
    return NULL;
306
0
  }
307
0
  newCom->tag = GF_ODF_ESD_UPDATE_TAG;
308
0
  return (GF_ODCom *)newCom;
309
0
}
310
311
GF_Err gf_odf_del_esd_update(GF_ESDUpdate *ESDUpdate)
312
0
{
313
0
  GF_Err e;
314
0
  if (! ESDUpdate) return GF_BAD_PARAM;
315
0
  while (gf_list_count(ESDUpdate->ESDescriptors)) {
316
0
    GF_Descriptor *tmp = (GF_Descriptor*)gf_list_get(ESDUpdate->ESDescriptors, 0);
317
0
    e = gf_odf_delete_descriptor(tmp);
318
0
    if (e) return e;
319
0
    e = gf_list_rem(ESDUpdate->ESDescriptors, 0);
320
0
    if (e) return e;
321
0
  }
322
0
  gf_list_del(ESDUpdate->ESDescriptors);
323
0
  gf_free(ESDUpdate);
324
0
  return GF_OK;
325
0
}
326
327
GF_Err AddToESDUpdate(GF_ESDUpdate *esdUp, GF_Descriptor *desc)
328
0
{
329
0
  if (! esdUp) return GF_BAD_PARAM;
330
0
  if (!desc) return GF_OK;
331
332
0
  switch (desc->tag) {
333
0
  case GF_ODF_ESD_TAG:
334
0
  case GF_ODF_ESD_REF_TAG:
335
0
    return gf_list_add(esdUp->ESDescriptors, desc);
336
337
0
  default:
338
0
    gf_odf_delete_descriptor(desc);
339
0
    return GF_OK;
340
0
  }
341
0
}
342
343
GF_Err gf_odf_read_esd_update(GF_BitStream *bs, GF_ESDUpdate *esdUp, u32 gf_odf_size_command)
344
0
{
345
0
  GF_Descriptor *tmp;
346
0
  u32 tmpSize = 0, nbBits = 0;
347
0
  GF_Err e = GF_OK;
348
0
  if (! esdUp) return GF_BAD_PARAM;
349
350
0
  esdUp->ODID = gf_bs_read_int(bs, 10);
351
0
  nbBits += 10;
352
  //very tricky, we're at the bit level here...
353
0
  while (1) {
354
0
    e = gf_odf_parse_descriptor(bs, &tmp, &tmpSize);
355
0
    if (e) return e;
356
0
    e = AddToESDUpdate(esdUp, tmp);
357
0
    if (e) return e;
358
0
    nbBits += ( tmpSize + gf_odf_size_field_size(tmpSize) ) * 8;
359
    //our com is aligned, so nbBits is between (gf_odf_size_command-1)*8 and gf_odf_size_command*8
360
0
    if ( ( (nbBits >(gf_odf_size_command-1)*8) && (nbBits <= gf_odf_size_command * 8))
361
0
            || (nbBits > gf_odf_size_command*8) ) { //this one is a security break
362
0
      break;
363
0
    }
364
0
  }
365
0
  if (nbBits > gf_odf_size_command * 8) return GF_ODF_INVALID_COMMAND;
366
  //Align our bitstream
367
0
  nbBits += gf_bs_align(bs);
368
0
  if (nbBits != gf_odf_size_command *8) return GF_ODF_INVALID_COMMAND;
369
0
  return e;
370
0
}
371
372
373
374
GF_Err gf_odf_size_esd_update(GF_ESDUpdate *esdUp, u32 *outSize)
375
0
{
376
0
  u32 i, BitSize, tmpSize;
377
0
  GF_Descriptor *tmp;
378
0
  if (!esdUp) return GF_BAD_PARAM;
379
380
0
  *outSize = 0;
381
0
  BitSize = 10;
382
0
  i=0;
383
0
  while ((tmp = (GF_Descriptor *)gf_list_enum(esdUp->ESDescriptors, &i))) {
384
0
    gf_odf_size_descriptor(tmp, &tmpSize);
385
0
    BitSize += ( tmpSize + gf_odf_size_field_size(tmpSize) ) * 8;
386
0
  }
387
0
  while ((s32) BitSize > 0) {
388
0
    BitSize -= 8;
389
0
    *outSize += 1;
390
0
  }
391
0
  return GF_OK;
392
0
}
393
GF_Err gf_odf_write_esd_update(GF_BitStream *bs, GF_ESDUpdate *esdUp)
394
0
{
395
0
  GF_Descriptor *tmp;
396
0
  GF_Err e;
397
0
  u32 size, i;
398
0
  if (! esdUp) return GF_BAD_PARAM;
399
400
0
  e = gf_odf_size_esd_update(esdUp, &size);
401
0
  if (e) return e;
402
0
  e = gf_odf_write_base_descriptor(bs, esdUp->tag, size);
403
0
  if (e) return e;
404
405
0
  gf_bs_write_int(bs, esdUp->ODID, 10);
406
0
  i=0;
407
0
  while ((tmp = (GF_Descriptor *)gf_list_enum(esdUp->ESDescriptors, &i))) {
408
0
    e = gf_odf_write_descriptor(bs, tmp);
409
0
    if (e) return e;
410
0
  }
411
  //OD commands are aligned
412
0
  gf_bs_align(bs);
413
0
  return GF_OK;
414
0
}
415
416
417
GF_ODCom *gf_odf_new_esd_remove()
418
0
{
419
0
  GF_ESDRemove *newCom = (GF_ESDRemove *) gf_malloc(sizeof(GF_ESDRemove));
420
0
  if (!newCom) return NULL;
421
0
  newCom->NbESDs = 0;
422
0
  newCom->ES_ID = NULL;
423
0
  newCom->tag = GF_ODF_ESD_REMOVE_TAG;
424
0
  return (GF_ODCom *)newCom;
425
0
}
426
427
GF_Err gf_odf_del_esd_remove(GF_ESDRemove *ESDRemove)
428
0
{
429
0
  if (! ESDRemove) return GF_BAD_PARAM;
430
0
  if (ESDRemove->ES_ID) gf_free(ESDRemove->ES_ID);
431
0
  gf_free(ESDRemove);
432
0
  return GF_OK;
433
0
}
434
435
436
GF_Err gf_odf_read_esd_remove(GF_BitStream *bs, GF_ESDRemove *esdRem, u32 gf_odf_size_command)
437
0
{
438
0
  u32 i = 0;
439
0
  if (! esdRem) return GF_BAD_PARAM;
440
441
0
  esdRem->ODID = gf_bs_read_int(bs, 10);
442
0
  /*aligned = */gf_bs_read_int(bs, 6);    //aligned
443
444
  //we have gf_odf_size_command - 2 bytes left, and this is our ES_ID[1...255]
445
  //this works because OD commands are aligned
446
0
  if (gf_odf_size_command < 2) return GF_ODF_INVALID_DESCRIPTOR;
447
0
  if (gf_odf_size_command == 2) {
448
0
    esdRem->NbESDs = 0;
449
0
    esdRem->ES_ID = NULL;
450
0
    return GF_OK;
451
0
  }
452
0
  esdRem->NbESDs = (gf_odf_size_command - 2) / 2;
453
0
  esdRem->ES_ID = (u16 *) gf_malloc(sizeof(u16) * esdRem->NbESDs);
454
0
  if (! esdRem->ES_ID) return GF_OUT_OF_MEM;
455
0
  for (i = 0; i < esdRem->NbESDs ; i++) {
456
0
    esdRem->ES_ID[i] = gf_bs_read_int(bs, 16);
457
0
  }
458
  //OD commands are aligned (but we should already be aligned....
459
0
  /*nbBits = */gf_bs_align(bs);
460
0
  return GF_OK;
461
0
}
462
463
GF_Err gf_odf_size_esd_remove(GF_ESDRemove *esdRem, u32 *outSize)
464
0
{
465
0
  if (!esdRem) return GF_BAD_PARAM;
466
0
  *outSize = 2 + 2 * esdRem->NbESDs;
467
0
  return GF_OK;
468
0
}
469
GF_Err gf_odf_write_esd_remove(GF_BitStream *bs, GF_ESDRemove *esdRem)
470
0
{
471
0
  GF_Err e;
472
0
  u32 size, i;
473
0
  if (! esdRem) return GF_BAD_PARAM;
474
475
0
  e = gf_odf_size_esd_remove(esdRem, &size);
476
0
  if (e) return e;
477
0
  e = gf_odf_write_base_descriptor(bs, esdRem->tag, size);
478
0
  if (e) return e;
479
480
0
  gf_bs_write_int(bs, esdRem->ODID, 10);
481
0
  gf_bs_write_int(bs, 0, 6);    //aligned
482
0
  for (i = 0; i < esdRem->NbESDs ; i++) {
483
0
    gf_bs_write_int(bs, esdRem->ES_ID[i], 16);
484
0
  }
485
  //OD commands are aligned (but we are already aligned....
486
0
  gf_bs_align(bs);
487
0
  return GF_OK;
488
0
}
489
490
#ifndef GPAC_MINIMAL_ODF
491
492
GF_ODCom *gf_odf_new_ipmp_remove()
493
{
494
  GF_IPMPRemove *newCom = (GF_IPMPRemove *) gf_malloc(sizeof(GF_IPMPRemove));
495
  if (!newCom) return NULL;
496
  newCom->IPMPDescID  =NULL;
497
  newCom->NbIPMPDs = 0;
498
  newCom->tag = GF_ODF_IPMP_REMOVE_TAG;
499
  return (GF_ODCom *)newCom;
500
}
501
502
GF_Err gf_odf_del_ipmp_remove(GF_IPMPRemove *IPMPDRemove)
503
{
504
  if (! IPMPDRemove) return GF_BAD_PARAM;
505
  if (IPMPDRemove->IPMPDescID) gf_free(IPMPDRemove->IPMPDescID);
506
  gf_free(IPMPDRemove);
507
  return GF_OK;
508
}
509
510
GF_Err gf_odf_read_ipmp_remove(GF_BitStream *bs, GF_IPMPRemove *ipmpRem, u32 gf_odf_size_command)
511
{
512
  u32 i;
513
  if (! ipmpRem) return GF_BAD_PARAM;
514
515
  //we have gf_odf_size_command bytes left, and this is our IPMPD_ID[1...255]
516
  //this works because OD commands are aligned
517
  if (!gf_odf_size_command) return GF_OK;
518
519
  ipmpRem->NbIPMPDs = gf_odf_size_command;
520
  ipmpRem->IPMPDescID = (u8 *) gf_malloc(sizeof(u8) * ipmpRem->NbIPMPDs);
521
  if (! ipmpRem->IPMPDescID) return GF_OUT_OF_MEM;
522
523
  for (i = 0; i < ipmpRem->NbIPMPDs; i++) {
524
    ipmpRem->IPMPDescID[i] = gf_bs_read_int(bs, 8);
525
  }
526
  //OD commands are aligned
527
  gf_bs_align(bs);
528
  return GF_OK;
529
}
530
531
GF_Err gf_odf_size_ipmp_remove(GF_IPMPRemove *ipmpRem, u32 *outSize)
532
{
533
  if (!ipmpRem) return GF_BAD_PARAM;
534
535
  *outSize = ipmpRem->NbIPMPDs;
536
  return GF_OK;
537
}
538
GF_Err gf_odf_write_ipmp_remove(GF_BitStream *bs, GF_IPMPRemove *ipmpRem)
539
{
540
  GF_Err e;
541
  u32 size, i;
542
  if (! ipmpRem) return GF_BAD_PARAM;
543
544
  e = gf_odf_size_ipmp_remove(ipmpRem, &size);
545
  if (e) return e;
546
  e = gf_odf_write_base_descriptor(bs, ipmpRem->tag, size);
547
  if (e) return e;
548
549
  for (i = 0; i < ipmpRem->NbIPMPDs; i++) {
550
    gf_bs_write_int(bs, ipmpRem->IPMPDescID[i], 8);
551
  }
552
  //OD commands are aligned
553
  gf_bs_align(bs);
554
  return GF_OK;
555
}
556
557
GF_ODCom *gf_odf_new_ipmp_update()
558
{
559
  GF_IPMPUpdate *newCom = (GF_IPMPUpdate *) gf_malloc(sizeof(GF_IPMPUpdate));
560
  if (!newCom) return NULL;
561
  newCom->IPMPDescList = gf_list_new();
562
  if (! newCom->IPMPDescList) {
563
    gf_free(newCom);
564
    return NULL;
565
  }
566
  newCom->tag = GF_ODF_IPMP_UPDATE_TAG;
567
  return (GF_ODCom *)newCom;
568
}
569
570
GF_Err gf_odf_del_ipmp_update(GF_IPMPUpdate *IPMPDUpdate)
571
{
572
  GF_Err e;
573
  if (! IPMPDUpdate) return GF_BAD_PARAM;
574
  while (gf_list_count(IPMPDUpdate->IPMPDescList)) {
575
    GF_Descriptor *tmp = (GF_Descriptor*)gf_list_get(IPMPDUpdate->IPMPDescList, 0);
576
    e = gf_odf_delete_descriptor(tmp);
577
    if (e) return e;
578
    e = gf_list_rem(IPMPDUpdate->IPMPDescList, 0);
579
    if (e) return e;
580
  }
581
  gf_list_del(IPMPDUpdate->IPMPDescList);
582
  gf_free(IPMPDUpdate);
583
  return GF_OK;
584
}
585
586
GF_Err AddToIPMPDUpdate(GF_IPMPUpdate *ipmpUp, GF_Descriptor *desc)
587
{
588
  if (! ipmpUp) return GF_BAD_PARAM;
589
  if (!desc) return GF_OK;
590
591
  switch (desc->tag) {
592
  case GF_ODF_IPMP_TAG:
593
    return gf_list_add(ipmpUp->IPMPDescList, desc);
594
  default:
595
    gf_odf_delete_descriptor(desc);
596
    return GF_OK;
597
  }
598
}
599
600
GF_Err gf_odf_read_ipmp_update(GF_BitStream *bs, GF_IPMPUpdate *ipmpUp, u32 gf_odf_size_command)
601
{
602
  GF_Descriptor *tmp;
603
  u32 tmpSize = 0, nbBytes = 0;
604
  GF_Err e = GF_OK;
605
  if (! ipmpUp) return GF_BAD_PARAM;
606
607
  while (nbBytes < gf_odf_size_command) {
608
    e = gf_odf_parse_descriptor(bs, &tmp, &tmpSize);
609
    if (e) return e;
610
    e = AddToIPMPDUpdate(ipmpUp, tmp);
611
    if (e) return e;
612
    nbBytes += tmpSize + gf_odf_size_field_size(tmpSize);
613
  }
614
  //OD commands are aligned
615
  gf_bs_align(bs);
616
  if (nbBytes != gf_odf_size_command) return GF_ODF_INVALID_COMMAND;
617
  return e;
618
}
619
620
621
GF_Err gf_odf_size_ipmp_update(GF_IPMPUpdate *ipmpUp, u32 *outSize)
622
{
623
  GF_Descriptor *tmp;
624
  u32 i, tmpSize;
625
  if (!ipmpUp) return GF_BAD_PARAM;
626
627
  *outSize = 0;
628
  i=0;
629
  while ((tmp = (GF_Descriptor *)gf_list_enum(ipmpUp->IPMPDescList, &i))) {
630
    gf_odf_size_descriptor(tmp, &tmpSize);
631
    *outSize += tmpSize + gf_odf_size_field_size(tmpSize);
632
  }
633
  return GF_OK;
634
}
635
GF_Err gf_odf_write_ipmp_update(GF_BitStream *bs, GF_IPMPUpdate *ipmpUp)
636
{
637
  GF_Err e;
638
  GF_Descriptor *tmp;
639
  u32 size, i;
640
  if (! ipmpUp) return GF_BAD_PARAM;
641
642
  e = gf_odf_size_ipmp_update(ipmpUp, &size);
643
  if (e) return e;
644
  e = gf_odf_write_base_descriptor(bs, ipmpUp->tag, size);
645
  if (e) return e;
646
647
  i=0;
648
  while ((tmp = (GF_Descriptor *)gf_list_enum(ipmpUp->IPMPDescList, &i))) {
649
    e = gf_odf_write_descriptor(bs, tmp);
650
    if (e) return e;
651
  }
652
  //OD commands are aligned
653
  gf_bs_align(bs);
654
  return GF_OK;
655
}
656
#endif
657