Coverage Report

Created: 2025-11-09 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpac/src/odf/odf_codec.c
Line
Count
Source
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
#include <gpac/internal/odf_dev.h>
27
28
/************************************************************
29
    Object GF_Descriptor Codec Functions
30
************************************************************/
31
32
GF_EXPORT
33
GF_ODCodec *gf_odf_codec_new()
34
0
{
35
0
  GF_ODCodec *codec;
36
0
  GF_List *comList;
37
38
0
  comList = gf_list_new();
39
0
  if (!comList) return NULL;
40
41
0
  codec = (GF_ODCodec *) gf_malloc(sizeof(GF_ODCodec));
42
0
  if (!codec) {
43
0
    gf_list_del(comList);
44
0
    return NULL;
45
0
  }
46
  //the bitstream is always NULL. It is created on the fly for access unit processing only
47
0
  codec->bs = NULL;
48
0
  codec->CommandList = comList;
49
0
  return codec;
50
0
}
51
52
GF_EXPORT
53
void gf_odf_codec_del(GF_ODCodec *codec)
54
0
{
55
0
  if (!codec) return;
56
57
0
  while (gf_list_count(codec->CommandList)) {
58
0
    GF_ODCom *com = (GF_ODCom *)gf_list_get(codec->CommandList, 0);
59
0
    gf_odf_delete_command(com);
60
0
    gf_list_rem(codec->CommandList, 0);
61
0
  }
62
0
  gf_list_del(codec->CommandList);
63
0
  if (codec->bs) gf_bs_del(codec->bs);
64
0
  gf_free(codec);
65
0
}
66
67
68
/************************************************************
69
    Codec Encoder Functions
70
************************************************************/
71
72
GF_EXPORT
73
GF_Err gf_odf_codec_add_com(GF_ODCodec *codec, GF_ODCom *command)
74
0
{
75
0
  if (!codec || !command) return GF_BAD_PARAM;
76
0
  return gf_list_add(codec->CommandList, command);
77
0
}
78
79
GF_EXPORT
80
GF_Err gf_odf_codec_encode(GF_ODCodec *codec, u32 cleanup_type)
81
0
{
82
0
  GF_ODCom *com;
83
0
  GF_Err e = GF_OK;
84
0
  u32 i;
85
86
0
  if (!codec) return GF_BAD_PARAM;
87
88
  //check our bitstream: if existing, this means the previous encoded AU was not retrieved
89
  //we DON'T allow that
90
0
  if (codec->bs) return GF_BAD_PARAM;
91
0
  codec->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
92
0
  if (!codec->bs) return GF_OUT_OF_MEM;
93
94
  /*encode each command*/
95
0
  i = 0;
96
0
  while ((com = (GF_ODCom *)gf_list_enum(codec->CommandList, &i))) {
97
0
    e = gf_odf_write_command(codec->bs, com);
98
0
    if (e) goto err_exit;
99
    //don't forget OD Commands are aligned...
100
0
    gf_bs_align(codec->bs);
101
0
  }
102
103
//if an error occurs, delete the GF_BitStream and empty the codec
104
0
err_exit:
105
0
  if (e) {
106
0
    gf_bs_del(codec->bs);
107
0
    codec->bs = NULL;
108
0
  }
109
0
  if (cleanup_type==1) {
110
0
    while (gf_list_count(codec->CommandList)) {
111
0
      com = (GF_ODCom *)gf_list_get(codec->CommandList, 0);
112
0
      gf_odf_delete_command(com);
113
0
      gf_list_rem(codec->CommandList, 0);
114
0
    }
115
0
  }
116
0
  if (cleanup_type==0) {
117
0
    gf_list_reset(codec->CommandList);
118
0
  }
119
0
  return e;
120
0
}
121
122
GF_EXPORT
123
GF_Err gf_odf_codec_get_au(GF_ODCodec *codec, u8 **outAU, u32 *au_length)
124
0
{
125
0
  if (!codec || !codec->bs || !outAU || *outAU) return GF_BAD_PARAM;
126
0
  gf_bs_get_content(codec->bs, outAU, au_length);
127
0
  gf_bs_del(codec->bs);
128
0
  codec->bs = NULL;
129
0
  return GF_OK;
130
0
}
131
132
133
134
/************************************************************
135
    Codec Decoder Functions
136
************************************************************/
137
138
GF_EXPORT
139
GF_Err gf_odf_codec_set_au(GF_ODCodec *codec, const u8 *au, u32 au_length)
140
0
{
141
0
  if (!codec ) return GF_BAD_PARAM;
142
0
  if (!au || !au_length) return GF_OK;
143
144
  //if the command list is not empty, this is an error
145
0
  if (gf_list_count(codec->CommandList)) return GF_BAD_PARAM;
146
147
  //the bitStream should not be here
148
0
  if (codec->bs) return GF_BAD_PARAM;
149
150
0
  codec->bs = gf_bs_new(au, (u64) au_length, (unsigned char)GF_BITSTREAM_READ);
151
0
  if (!codec->bs) return GF_OUT_OF_MEM;
152
0
  return GF_OK;
153
0
}
154
155
156
GF_EXPORT
157
GF_Err gf_odf_codec_decode(GF_ODCodec *codec)
158
0
{
159
0
  GF_Err e = GF_OK;
160
0
  u32 size = 0, comSize, bufSize;
161
0
  GF_ODCom *com;
162
163
0
  if (!codec || !codec->bs) return GF_BAD_PARAM;
164
165
0
  bufSize = (u32) gf_bs_available(codec->bs);
166
0
  while (size < bufSize) {
167
0
    e = gf_odf_parse_command(codec->bs, &com, &comSize);
168
0
    if (e) goto err_exit;
169
0
    gf_list_add(codec->CommandList, com);
170
0
    size += comSize + gf_odf_size_field_size(comSize);
171
    //OD Commands are aligned
172
0
    gf_bs_align(codec->bs);
173
0
  }
174
  //then delete our bitstream
175
0
  gf_bs_del(codec->bs);
176
0
  codec->bs = NULL;
177
0
  if (size != bufSize) {
178
0
    e = GF_ODF_INVALID_COMMAND;
179
0
    goto err_exit;
180
0
  }
181
0
  return e;
182
183
0
err_exit:
184
0
  if (codec->bs) {
185
0
    gf_bs_del(codec->bs);
186
0
    codec->bs = NULL;
187
0
  }
188
0
  while (gf_list_count(codec->CommandList)) {
189
0
    com = (GF_ODCom*)gf_list_get(codec->CommandList, 0);
190
0
    gf_odf_delete_command(com);
191
0
    gf_list_rem(codec->CommandList, 0);
192
0
  }
193
0
  return e;
194
0
}
195
196
//get the first command in the codec and remove the entry
197
GF_EXPORT
198
GF_ODCom *gf_odf_codec_get_com(GF_ODCodec *codec)
199
0
{
200
0
  GF_ODCom *com;
201
0
  if (!codec || codec->bs) return NULL;
202
0
  com = (GF_ODCom*)gf_list_get(codec->CommandList, 0);
203
0
  if (com) gf_list_rem(codec->CommandList, 0);
204
0
  return com;
205
0
}
206
207
208
209
/************************************************************
210
    OD Commands Functions
211
************************************************************/
212
213
//some easy way to get an OD GF_ODCom...
214
GF_EXPORT
215
GF_ODCom *gf_odf_com_new(u8 tag)
216
0
{
217
0
  GF_ODCom *newcom;
218
219
0
  newcom = gf_odf_create_command(tag);
220
0
  newcom->tag = tag;
221
0
  return (GF_ODCom *)newcom;
222
0
}
223
224
//  ... and to delete it
225
GF_EXPORT
226
GF_Err gf_odf_com_del(GF_ODCom **com)
227
0
{
228
0
  GF_Err e;
229
0
  e = gf_odf_delete_command(*com);
230
0
  *com = NULL;
231
0
  return e;
232
0
}
233
234
235
/************************************************************
236
    Object Descriptors Functions
237
************************************************************/
238
239
//some easy way to get an mpeg4 descriptor ...
240
GF_EXPORT
241
GF_Descriptor *gf_odf_desc_new(u8 tag)
242
49.8k
{
243
49.8k
  GF_Descriptor *newdesc;
244
49.8k
  newdesc = gf_odf_create_descriptor(tag);
245
49.8k
  newdesc->tag = tag;
246
49.8k
  return (GF_Descriptor *)newdesc;
247
49.8k
}
248
249
//  ... and to delete it
250
GF_EXPORT
251
void gf_odf_desc_del(GF_Descriptor *desc)
252
72.7k
{
253
72.7k
  if (desc) gf_odf_delete_descriptor(desc);
254
72.7k
}
255
256
//this functions will destroy the descriptors in a list but not the list
257
GF_EXPORT
258
GF_Err gf_odf_desc_list_del(GF_List *descList)
259
10.1k
{
260
10.1k
  GF_Err e;
261
262
10.1k
  if (! descList) return GF_BAD_PARAM;
263
264
533k
  while (gf_list_count(descList)) {
265
523k
    GF_Descriptor *tmp = (GF_Descriptor*)gf_list_get(descList, 0);
266
523k
    gf_list_rem(descList, 0);
267
523k
    e = gf_odf_delete_descriptor(tmp);
268
523k
    if (e) return e;
269
523k
  }
270
10.1k
  return GF_OK;
271
10.1k
}
272
273
274
275
GF_EXPORT
276
GF_ESD *gf_odf_desc_esd_new(u32 sl_predefined)
277
15.3k
{
278
15.3k
  GF_ESD *esd;
279
15.3k
  esd = (GF_ESD *) gf_odf_desc_new(GF_ODF_ESD_TAG);
280
15.3k
  esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG);
281
15.3k
  esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
282
15.3k
  esd->slConfig = (GF_SLConfig *) gf_odf_new_slc((u8) sl_predefined);
283
15.3k
  return esd;
284
15.3k
}
285
286
287
//use this function to decode a standalone descriptor
288
//the desc MUST be formatted with tag and size field!!!
289
GF_EXPORT
290
GF_Err gf_odf_desc_read(u8 *raw_desc, u32 descSize, GF_Descriptor **outDesc)
291
40.7k
{
292
40.7k
  GF_Err e;
293
40.7k
  u32 size;
294
40.7k
  GF_BitStream *bs;
295
40.7k
  if (!raw_desc || !descSize) return GF_BAD_PARAM;
296
297
40.5k
  bs = gf_bs_new(raw_desc, (u64) descSize, GF_BITSTREAM_READ);
298
40.5k
  if (!bs) return GF_OUT_OF_MEM;
299
300
40.5k
  size = 0;
301
40.5k
  e = gf_odf_parse_descriptor(bs, outDesc, &size);
302
  //the size dosn't have the header in it
303
40.5k
  size += gf_odf_size_field_size(size);
304
  /*
305
    if (size != descSize) {
306
      if (*outDesc) gf_odf_delete_descriptor(*outDesc);
307
      *outDesc = NULL;
308
      e = GF_ODF_INVALID_DESCRIPTOR;
309
    }
310
  */
311
312
40.5k
  gf_bs_del(bs);
313
40.5k
  return e;
314
40.5k
}
315
316
//use this function to encode a standalone descriptor
317
//the desc will be formatted with tag and size field
318
GF_EXPORT
319
GF_Err gf_odf_desc_write_bs(GF_Descriptor *desc, GF_BitStream *bs)
320
50.7k
{
321
50.7k
  GF_Err e;
322
50.7k
  if (!desc || !bs) return GF_BAD_PARAM;
323
324
  //then encode our desc...
325
50.7k
  e = gf_odf_write_descriptor(bs, desc);
326
50.7k
  if (e) return e;
327
  
328
23.5k
  return GF_OK;
329
50.7k
}
330
331
GF_EXPORT
332
GF_Err gf_odf_desc_write(GF_Descriptor *desc, u8 **outEncDesc, u32 *outSize)
333
50.7k
{
334
50.7k
  GF_Err e;
335
50.7k
  GF_BitStream *bs;
336
50.7k
  if (!desc || !outEncDesc || !outSize) return GF_BAD_PARAM;
337
50.7k
  *outEncDesc = NULL;
338
50.7k
  *outSize = 0;
339
340
50.7k
  bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
341
50.7k
  if (!bs) return GF_OUT_OF_MEM;
342
343
50.7k
  e = gf_odf_desc_write_bs(desc, bs);
344
  
345
  //then get the content from our bitstream
346
50.7k
  gf_bs_get_content(bs, outEncDesc, outSize);
347
50.7k
  gf_bs_del(bs);
348
50.7k
  return e;
349
50.7k
}
350
351
352
//use this function to get the size of a standalone descriptor
353
GF_EXPORT
354
u32 gf_odf_desc_size(GF_Descriptor *desc)
355
126
{
356
126
  u32 descSize;
357
126
  GF_Err e;
358
359
126
  if (!desc) return GF_BAD_PARAM;
360
  //get the descriptor length
361
126
  e = gf_odf_size_descriptor(desc, &descSize);
362
126
  if (e) return 0;
363
  //add the header length
364
126
  descSize += gf_odf_size_field_size(descSize);
365
126
  return descSize;
366
367
126
}
368
369
//this is useful to duplicate on the fly a descriptor (mainly for authoring purposes)
370
GF_EXPORT
371
GF_Err gf_odf_desc_copy(GF_Descriptor *inDesc, GF_Descriptor **outDesc)
372
50.6k
{
373
50.6k
  GF_Err e;
374
50.6k
  u8 *desc;
375
50.6k
  u32 size, oti=0;
376
377
  //patch for esd copy, we now signal codecid (32 bit) in OTI (8 bits)
378
50.6k
  if (inDesc->tag == GF_ODF_ESD_TAG) {
379
4.09k
    GF_ESD *esd = (GF_ESD *)inDesc;
380
4.09k
    if (esd->decoderConfig) {
381
1.03k
      oti = esd->decoderConfig->objectTypeIndication;
382
1.03k
      esd->decoderConfig->objectTypeIndication = 0;
383
1.03k
    }
384
4.09k
  }
385
386
  //warning: here we get some data allocated
387
50.6k
  e = gf_odf_desc_write(inDesc, &desc, &size);
388
50.6k
  if (e) return e;
389
23.4k
  e = gf_odf_desc_read(desc, size, outDesc);
390
23.4k
  gf_free(desc);
391
23.4k
  if (oti && !e) {
392
1.01k
    GF_ESD *esd = (GF_ESD *)inDesc;
393
1.01k
    GF_ESD *out_esd = (GF_ESD *)*outDesc;
394
1.01k
    if (esd->decoderConfig) esd->decoderConfig->objectTypeIndication = oti;
395
1.01k
    if (out_esd->decoderConfig) out_esd->decoderConfig->objectTypeIndication = oti;
396
1.01k
  }
397
23.4k
  return e;
398
50.6k
}
399
400
/************************************************************
401
    Object Descriptors Edit Functions
402
************************************************************/
403
404
//This functions handles internally what desc can be added to another desc
405
//and adds it. NO DUPLICATION of the descriptor, so
406
//once a desc is added to its parent, destroying the parent WILL destroy this desc
407
GF_EXPORT
408
GF_Err gf_odf_desc_add_desc(GF_Descriptor *parentDesc, GF_Descriptor *newDesc)
409
50.2k
{
410
50.2k
  GF_DecoderConfig *dcd;
411
412
  //our ADD definition
413
50.2k
  GF_Err AddDescriptorToOD(GF_ObjectDescriptor *od, GF_Descriptor *desc);
414
50.2k
  GF_Err AddDescriptorToIOD(GF_InitialObjectDescriptor *iod, GF_Descriptor *desc);
415
50.2k
  GF_Err AddDescriptorToESD(GF_ESD *esd, GF_Descriptor *desc);
416
50.2k
  GF_Err AddDescriptorToIsomIOD(GF_IsomInitialObjectDescriptor *iod, GF_Descriptor *desc);
417
50.2k
  GF_Err AddDescriptorToIsomOD(GF_IsomObjectDescriptor *od, GF_Descriptor *desc);
418
419
50.2k
  if (!parentDesc || !newDesc) return GF_BAD_PARAM;
420
421
21.5k
  switch (parentDesc->tag) {
422
  //these are container descriptors
423
0
  case GF_ODF_OD_TAG:
424
0
    return AddDescriptorToOD((GF_ObjectDescriptor *)parentDesc, newDesc);
425
0
  case GF_ODF_IOD_TAG:
426
0
    return AddDescriptorToIOD((GF_InitialObjectDescriptor *)parentDesc, newDesc);
427
21.5k
  case GF_ODF_ESD_TAG:
428
21.5k
    return AddDescriptorToESD((GF_ESD *)parentDesc, newDesc);
429
0
  case GF_ODF_DCD_TAG:
430
0
    dcd = (GF_DecoderConfig *)parentDesc;
431
0
    if ((newDesc->tag == GF_ODF_DSI_TAG)
432
0
            || (newDesc->tag == GF_ODF_BIFS_CFG_TAG)
433
0
            || (newDesc->tag == GF_ODF_UI_CFG_TAG)
434
0
            || (newDesc->tag == GF_ODF_TEXT_CFG_TAG)
435
0
       ) {
436
0
      if (dcd->decoderSpecificInfo) return GF_ODF_FORBIDDEN_DESCRIPTOR;
437
0
      dcd->decoderSpecificInfo = (GF_DefaultDescriptor *) newDesc;
438
0
      return GF_OK;
439
0
    } else if (newDesc->tag == GF_ODF_EXT_PL_TAG) {
440
0
      return gf_list_add(dcd->profileLevelIndicationIndexDescriptor, newDesc);
441
0
    }
442
0
    return GF_ODF_FORBIDDEN_DESCRIPTOR;
443
444
0
  case GF_ODF_TEXT_CFG_TAG:
445
0
    if (newDesc->tag != GF_ODF_TX3G_TAG) return GF_ODF_FORBIDDEN_DESCRIPTOR;
446
0
    return gf_list_add(((GF_TextConfig *)parentDesc)->sample_descriptions, newDesc);
447
448
0
  case GF_ODF_QOS_TAG:
449
0
    return GF_BAD_PARAM;
450
451
  //MP4 File Format tags
452
0
  case GF_ODF_ISOM_IOD_TAG:
453
0
    return AddDescriptorToIsomIOD((GF_IsomInitialObjectDescriptor *)parentDesc, newDesc);
454
0
  case GF_ODF_ISOM_OD_TAG:
455
0
    return AddDescriptorToIsomOD((GF_IsomObjectDescriptor *)parentDesc, newDesc);
456
457
0
  case GF_ODF_IPMP_TL_TAG:
458
0
    if (newDesc->tag!=GF_ODF_IPMP_TOOL_TAG) return GF_BAD_PARAM;
459
0
    return gf_list_add(((GF_IPMP_ToolList *)parentDesc)->ipmp_tools, newDesc);
460
461
0
  case GF_ODF_BIFS_CFG_TAG:
462
0
  {
463
0
    GF_BIFSConfig *cfg = (GF_BIFSConfig *)parentDesc;
464
0
    if (newDesc->tag!=GF_ODF_ELEM_MASK_TAG) return GF_BAD_PARAM;
465
0
    if (!cfg->elementaryMasks) cfg->elementaryMasks = gf_list_new();
466
0
    return gf_list_add(cfg->elementaryMasks, newDesc);
467
0
  }
468
0
  default:
469
0
    return GF_ODF_FORBIDDEN_DESCRIPTOR;
470
21.5k
  }
471
21.5k
}
472
473
474
475
/*****************************************************************************************
476
    Since IPMP V2, we introduce a new set of functions to read / write a list of
477
  descriptors that have no containers (a bit like an OD command, but for descriptors)
478
    This is useful for IPMPv2 DecoderSpecificInfo which contains a set of
479
  IPMP_Declarators.
480
    As it could be used for other purposes we keep it generic
481
  You must create the list yourself, the functions just encode/decode from/to the list
482
483
  These functions are also used in mp4 for extension descriptor in LASeR and AVC sample descriptions
484
*****************************************************************************************/
485
486
GF_EXPORT
487
GF_Err gf_odf_desc_list_read(u8 *raw_list, u32 raw_size, GF_List *descList)
488
9.40k
{
489
9.40k
  GF_BitStream *bs;
490
9.40k
  u32 size, desc_size;
491
9.40k
  GF_Descriptor *desc;
492
9.40k
  GF_Err e = GF_OK;
493
494
9.40k
  if (!descList || !raw_list || !raw_size) return GF_BAD_PARAM;
495
496
9.40k
  bs = gf_bs_new(raw_list, raw_size, GF_BITSTREAM_READ);
497
9.40k
  if (!bs) return GF_OUT_OF_MEM;
498
499
9.40k
  size = 0;
500
532k
  while (size < raw_size) {
501
527k
    e = gf_odf_parse_descriptor(bs, &desc, &desc_size);
502
527k
    if (e) goto exit;
503
523k
    gf_list_add(descList, desc);
504
523k
    size += desc_size + gf_odf_size_field_size(desc_size);
505
523k
  }
506
507
9.40k
exit:
508
  //then delete our bitstream
509
9.40k
  gf_bs_del(bs);
510
9.40k
  if (size != raw_size) e = GF_ODF_INVALID_DESCRIPTOR;
511
9.40k
  return e;
512
9.40k
}
513
514
515
GF_EXPORT
516
GF_Err gf_odf_desc_list_write(GF_List *descList, u8 **outEncList, u32 *outSize)
517
0
{
518
0
  GF_BitStream *bs;
519
0
  GF_Err e;
520
521
0
  if (!descList || !outEncList || *outEncList || !outSize) return GF_BAD_PARAM;
522
523
0
  *outSize = 0;
524
525
0
  bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
526
0
  if (!bs) return GF_OUT_OF_MEM;
527
528
0
  e = gf_odf_write_descriptor_list(bs, descList);
529
0
  if (e) {
530
0
    gf_bs_del(bs);
531
0
    return e;
532
0
  }
533
534
0
  gf_bs_get_content(bs, outEncList, outSize);
535
0
  gf_bs_del(bs);
536
0
  return GF_OK;
537
0
}
538
539
GF_EXPORT
540
GF_Err gf_odf_desc_list_size(GF_List *descList, u32 *outSize)
541
0
{
542
0
  return gf_odf_size_descriptor_list(descList, outSize);
543
0
}
544
545
546
547
GF_Err gf_odf_codec_apply_com(GF_ODCodec *codec, GF_ODCom *command)
548
0
{
549
0
  GF_ODCom *com;
550
0
  GF_ODUpdate *odU, *odU_o;
551
0
  u32 i, count;
552
0
  count = gf_list_count(codec->CommandList);
553
554
0
  switch (command->tag) {
555
0
  case GF_ODF_OD_REMOVE_TAG:
556
0
    for (i=0; i<count; i++) {
557
0
      com = (GF_ODCom *)gf_list_get(codec->CommandList, i);
558
      /*process OD updates*/
559
0
      if (com->tag==GF_ODF_OD_UPDATE_TAG) {
560
0
        u32 count2, j, k;
561
0
        GF_ODRemove *odR = (GF_ODRemove *) command;
562
0
        odU = (GF_ODUpdate *)com;
563
0
        count2 = gf_list_count(odU->objectDescriptors);
564
        /*remove all descs*/
565
0
        for (k=0; k<count2; k++) {
566
0
          GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k);
567
0
          for (j=0; j<odR->NbODs; j++) {
568
0
            if (od->objectDescriptorID==odR->OD_ID[j]) {
569
0
              gf_list_rem(odU->objectDescriptors, k);
570
0
              k--;
571
0
              count2--;
572
0
              gf_odf_desc_del((GF_Descriptor *)od);
573
0
              break;
574
0
            }
575
0
          }
576
0
        }
577
0
        if (!gf_list_count(odU->objectDescriptors)) {
578
0
          gf_list_rem(codec->CommandList, i);
579
0
          i--;
580
0
          count--;
581
0
        }
582
0
      }
583
      /*process ESD updates*/
584
0
      else if (com->tag==GF_ODF_ESD_UPDATE_TAG) {
585
0
        u32 j;
586
0
        GF_ODRemove *odR = (GF_ODRemove *) command;
587
0
        GF_ESDUpdate *esdU = (GF_ESDUpdate*)com;
588
0
        for (j=0; j<odR->NbODs; j++) {
589
0
          if (esdU->ODID==odR->OD_ID[j]) {
590
0
            gf_list_rem(codec->CommandList, i);
591
0
            i--;
592
0
            count--;
593
0
            gf_odf_com_del((GF_ODCom**)&esdU);
594
0
            break;
595
0
          }
596
0
        }
597
0
      }
598
      /*process ESD remove*/
599
0
      else if (com->tag==GF_ODF_ESD_REMOVE_TAG) {
600
0
        u32 j;
601
0
        GF_ODRemove *odR = (GF_ODRemove *) command;
602
0
        GF_ESDRemove *esdR = (GF_ESDRemove*)com;
603
0
        for (j=0; j<odR->NbODs; j++) {
604
0
          if (esdR->ODID==odR->OD_ID[j]) {
605
0
            gf_list_rem(codec->CommandList, i);
606
0
            i--;
607
0
            count--;
608
0
            gf_odf_com_del((GF_ODCom**)&esdR);
609
0
            break;
610
0
          }
611
0
        }
612
0
      }
613
0
    }
614
0
    return GF_OK;
615
0
  case GF_ODF_OD_UPDATE_TAG:
616
0
    odU_o = NULL;
617
0
    for (i=0; i<count; i++) {
618
0
      odU_o = (GF_ODUpdate*)gf_list_get(codec->CommandList, i);
619
      /*process OD updates*/
620
0
      if (odU_o->tag==GF_ODF_OD_UPDATE_TAG) break;
621
0
      odU_o = NULL;
622
0
    }
623
0
    if (!odU_o) {
624
0
      odU_o = (GF_ODUpdate *)gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
625
0
      gf_list_add(codec->CommandList, odU_o);
626
0
    }
627
0
    odU = (GF_ODUpdate*)command;
628
0
    count = gf_list_count(odU->objectDescriptors);
629
0
    for (i=0; i<count; i++) {
630
0
      Bool found = GF_FALSE;
631
0
      GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, i);
632
0
      u32 j, count2 = gf_list_count(odU_o->objectDescriptors);
633
0
      for (j=0; j<count2; j++) {
634
0
        GF_ObjectDescriptor *od2 = (GF_ObjectDescriptor *)gf_list_get(odU_o->objectDescriptors, j);
635
0
        if (od2->objectDescriptorID==od->objectDescriptorID) {
636
0
          found = GF_TRUE;
637
0
          break;
638
0
        }
639
0
      }
640
0
      if (!found) {
641
0
        GF_ObjectDescriptor *od_new;
642
0
        GF_Err e = gf_odf_desc_copy((GF_Descriptor*)od, (GF_Descriptor**)&od_new);
643
0
        if (e==GF_OK)
644
0
          gf_list_add(odU_o->objectDescriptors, od_new);
645
0
      }
646
647
0
    }
648
0
    return GF_OK;
649
0
  case GF_ODF_ESD_REMOVE_TAG:
650
0
    for (i=0; i<count; i++) {
651
0
      com = (GF_ODCom *)gf_list_get(codec->CommandList, i);
652
      /*process OD updates*/
653
0
      if (com->tag==GF_ODF_OD_UPDATE_TAG) {
654
0
        u32 count2, j, k, l;
655
0
        GF_ESDRemove *esdR = (GF_ESDRemove *) command;
656
0
        odU = (GF_ODUpdate *)com;
657
0
        count2 = gf_list_count(odU->objectDescriptors);
658
        /*remove all descs*/
659
0
        for (k=0; k<count2; k++) {
660
0
          GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k);
661
0
          for (j=0; j<gf_list_count(od->ESDescriptors); j++) {
662
0
            GF_ESD *esd = gf_list_get(od->ESDescriptors, j);
663
0
            for (l=0; l<esdR->NbESDs; l++) {
664
0
              if (esdR->ES_ID[l] == esd->ESID) {
665
0
                gf_list_rem(od->ESDescriptors, j);
666
0
                j--;
667
0
                gf_odf_desc_del((GF_Descriptor *)esd);
668
0
                break;
669
0
              }
670
0
            }
671
0
          }
672
0
        }
673
0
      }
674
      /*process ESD updates*/
675
0
      else if (com->tag==GF_ODF_ESD_UPDATE_TAG) {
676
0
        u32 j, k;
677
0
        GF_ESDRemove *esdR = (GF_ESDRemove *) command;
678
0
        GF_ESDUpdate *esdU = (GF_ESDUpdate*)com;
679
0
        for (j=0; j<gf_list_count(esdU->ESDescriptors); j++) {
680
0
          GF_ESD *esd = gf_list_get(esdU->ESDescriptors, j);
681
0
          for (k=0; k<esdR->NbESDs; k++) {
682
0
            if (esd->ESID == esdR->ES_ID[k]) {
683
0
              gf_list_rem(codec->CommandList, j);
684
0
              j--;
685
0
              gf_odf_desc_del((GF_Descriptor *)esd);
686
0
            }
687
0
          }
688
0
        }
689
0
        if (!gf_list_count(esdU->ESDescriptors)) {
690
0
          gf_list_rem(codec->CommandList, i);
691
0
          i--;
692
0
          count--;
693
0
          gf_odf_com_del((GF_ODCom**)&esdU);
694
0
        }
695
0
      }
696
0
    }
697
0
    return GF_OK;
698
0
  case GF_ODF_ESD_UPDATE_TAG:
699
0
    for (i=0; i<count; i++) {
700
0
      com = (GF_ODCom *)gf_list_get(codec->CommandList, i);
701
      /*process OD updates*/
702
0
      if (com->tag==GF_ODF_OD_UPDATE_TAG) {
703
0
        u32 count2, k, l;
704
0
        GF_ESDUpdate *esdU = (GF_ESDUpdate *) command;
705
0
        odU = (GF_ODUpdate *)com;
706
0
        count2 = gf_list_count(odU->objectDescriptors);
707
        /*remove all descs*/
708
0
        for (k=0; k<count2; k++) {
709
0
          GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k);
710
0
          if (od->objectDescriptorID==esdU->ODID) {
711
0
            GF_ESD *esd;
712
0
            while (gf_list_count(od->ESDescriptors)) {
713
0
              esd = gf_list_pop_back(od->ESDescriptors);
714
0
              gf_odf_desc_del((GF_Descriptor *)esd);
715
0
            }
716
0
            gf_list_transfer(od->ESDescriptors, esdU->ESDescriptors);
717
0
            l = 0;
718
0
            while ((esd = gf_list_enum(esdU->ESDescriptors, &l))) {
719
0
              GF_ESD *new_esd;
720
0
              GF_Err e = gf_odf_desc_copy((GF_Descriptor*)esd, (GF_Descriptor**)&new_esd);
721
0
              if (e==GF_OK)
722
0
                gf_list_add(od->ESDescriptors, new_esd);
723
0
            }
724
0
            break;
725
0
          }
726
0
        }
727
0
      }
728
      /*process ESD updates*/
729
0
      else if (com->tag==GF_ODF_ESD_UPDATE_TAG) {
730
0
        return GF_NOT_SUPPORTED;
731
0
      }
732
0
    }
733
0
    return GF_OK;
734
0
  }
735
0
  return GF_NOT_SUPPORTED;
736
0
}