Coverage Report

Created: 2026-03-10 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpac/src/isomedia/media_odf.c
Line
Count
Source
1
/*
2
 *      GPAC - Multimedia Framework C SDK
3
 *
4
 *      Authors: Jean Le Feuvre
5
 *      Copyright (c) Telecom ParisTech 2000-2025
6
 *          All rights reserved
7
 *
8
 *  This file is part of GPAC / ISO Media File Format 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/isomedia_dev.h>
27
28
#ifndef GPAC_DISABLE_ISOM
29
30
// Rewrite the good dependencies when an OD AU is extracted from the file
31
GF_Err Media_RewriteODFrame(GF_MediaBox *mdia, GF_ISOSample *sample)
32
0
{
33
0
  GF_Err e;
34
0
  GF_ODCodec *ODdecode;
35
0
  GF_ODCodec *ODencode;
36
0
  GF_ODCom *com;
37
38
  //the commands we proceed
39
0
  GF_ESDUpdate *esdU, *esdU2;
40
0
  GF_ESDRemove *esdR, *esdR2;
41
0
  GF_ODUpdate *odU, *odU2;
42
43
  //the desc they contain
44
0
  GF_ObjectDescriptor *od;
45
0
  GF_IsomObjectDescriptor *isom_od;
46
0
  GF_ESD *esd;
47
0
  GF_ES_ID_Ref *ref;
48
0
  GF_Descriptor *desc;
49
0
  GF_TrackReferenceTypeBox *mpod;
50
0
  u32 i, j, skipped;
51
52
0
  if (!mdia || !sample || !sample->data || !sample->dataLength) return GF_BAD_PARAM;
53
54
0
  mpod = NULL;
55
0
  e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
56
0
  if (e) return e;
57
  //no references, nothing to do...
58
0
  if (!mpod || !mpod->trackIDs) return GF_OK;
59
60
0
  ODdecode = gf_odf_codec_new();
61
0
  if (!ODdecode) return GF_OUT_OF_MEM;
62
0
  ODencode = gf_odf_codec_new();
63
0
  if (!ODencode) {
64
0
    gf_odf_codec_del(ODdecode);
65
0
    return GF_OUT_OF_MEM;
66
0
  }
67
0
  e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
68
0
  if (e) goto err_exit;
69
0
  e = gf_odf_codec_decode(ODdecode);
70
0
  if (e) goto err_exit;
71
72
0
  while (1) {
73
0
    com = gf_odf_codec_get_com(ODdecode);
74
0
    if (!com) break;
75
76
    //we only need to rewrite commands with ESDs inside: ESDUpdate and ODUpdate
77
0
    switch (com->tag) {
78
0
    case GF_ODF_OD_UPDATE_TAG:
79
0
      odU = (GF_ODUpdate *) com;
80
0
      odU2 = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
81
82
0
      i=0;
83
0
      while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
84
0
        switch (desc->tag) {
85
0
        case GF_ODF_OD_TAG:
86
0
        case GF_ODF_ISOM_OD_TAG:
87
        //IOD can be used in OD streams
88
0
        case GF_ODF_ISOM_IOD_TAG:
89
0
          break;
90
0
        default:
91
0
          return GF_ISOM_INVALID_FILE;
92
0
        }
93
0
        e = gf_odf_desc_copy(desc, (GF_Descriptor **)&isom_od);
94
0
        if (e) goto err_exit;
95
96
        //create our OD...
97
0
        if (desc->tag == GF_ODF_ISOM_IOD_TAG) {
98
0
          od = (GF_ObjectDescriptor *) gf_malloc(sizeof(GF_InitialObjectDescriptor));
99
0
        } else {
100
0
          od = (GF_ObjectDescriptor *) gf_malloc(sizeof(GF_ObjectDescriptor));
101
0
        }
102
0
        if (!od) {
103
0
          e = GF_OUT_OF_MEM;
104
0
          goto err_exit;
105
0
        }
106
0
        od->ESDescriptors = gf_list_new();
107
        //and duplicate...
108
0
        od->objectDescriptorID = isom_od->objectDescriptorID;
109
0
        od->tag = GF_ODF_OD_TAG;
110
0
        od->URLString = isom_od->URLString;
111
0
        isom_od->URLString = NULL;
112
0
        od->extensionDescriptors = isom_od->extensionDescriptors;
113
0
        isom_od->extensionDescriptors = NULL;
114
0
        od->IPMP_Descriptors = isom_od->IPMP_Descriptors;
115
0
        isom_od->IPMP_Descriptors = NULL;
116
0
        od->OCIDescriptors = isom_od->OCIDescriptors;
117
0
        isom_od->OCIDescriptors = NULL;
118
119
        //init as IOD
120
0
        if (isom_od->tag == GF_ODF_ISOM_IOD_TAG) {
121
0
          ((GF_InitialObjectDescriptor *)od)->audio_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->audio_profileAndLevel;
122
0
          ((GF_InitialObjectDescriptor *)od)->inlineProfileFlag = ((GF_IsomInitialObjectDescriptor *)isom_od)->inlineProfileFlag;
123
0
          ((GF_InitialObjectDescriptor *)od)->graphics_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->graphics_profileAndLevel;
124
0
          ((GF_InitialObjectDescriptor *)od)->OD_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->OD_profileAndLevel;
125
0
          ((GF_InitialObjectDescriptor *)od)->scene_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->scene_profileAndLevel;
126
0
          ((GF_InitialObjectDescriptor *)od)->visual_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->visual_profileAndLevel;
127
0
          ((GF_InitialObjectDescriptor *)od)->IPMPToolList = ((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList;
128
0
          ((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList = NULL;
129
0
        }
130
131
        //then rewrite the ESDesc
132
0
        j=0;
133
0
        while ((ref = (GF_ES_ID_Ref*)gf_list_enum(isom_od->ES_ID_RefDescriptors, &j))) {
134
0
          if (!mpod->trackIDs || !ref->trackRef || (ref->trackRef>mpod->trackIDCount)) continue;
135
          //if the ref index is not valid, skip this desc...
136
0
          if (gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1]) == NULL) continue;
137
          //OK, get the esd
138
0
          e = GetESDForTime(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1], sample->DTS, &esd);
139
0
          if (!e) e = gf_odf_desc_add_desc((GF_Descriptor *) od, (GF_Descriptor *) esd);
140
0
          if (e) {
141
0
            gf_odf_desc_del((GF_Descriptor *)od);
142
0
            gf_odf_com_del((GF_ODCom **)&odU2);
143
0
            gf_odf_desc_del((GF_Descriptor *)isom_od);
144
0
            gf_odf_com_del((GF_ODCom **)&odU);
145
0
            goto err_exit;
146
0
          }
147
148
0
        }
149
        //delete our desc
150
0
        gf_odf_desc_del((GF_Descriptor *)isom_od);
151
0
        gf_list_add(odU2->objectDescriptors, od);
152
0
      }
153
      //clean a bit
154
0
      gf_odf_com_del((GF_ODCom **)&odU);
155
0
      gf_odf_codec_add_com(ODencode, (GF_ODCom *)odU2);
156
0
      break;
157
158
0
    case GF_ODF_ESD_UPDATE_TAG:
159
0
      esdU = (GF_ESDUpdate *) com;
160
0
      esdU2 = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG);
161
0
      esdU2->ODID = esdU->ODID;
162
0
      i=0;
163
0
      while ((ref = (GF_ES_ID_Ref*)gf_list_enum(esdU->ESDescriptors, &i))) {
164
0
        if (!mpod->trackIDs || !ref->trackRef || (ref->trackRef>mpod->trackIDCount)) continue;
165
        //if the ref index is not valid, skip this desc...
166
0
        if (gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1]) == NULL) continue;
167
        //OK, get the esd
168
0
        e = GetESDForTime(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1], sample->DTS, &esd);
169
0
        if (e) goto err_exit;
170
0
        gf_list_add(esdU2->ESDescriptors, esd);
171
0
      }
172
0
      gf_odf_com_del((GF_ODCom **)&esdU);
173
0
      gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdU2);
174
0
      break;
175
176
    //brand new case: the ESRemove follows the same principle according to the spec...
177
0
    case GF_ODF_ESD_REMOVE_REF_TAG:
178
      //both commands have the same structure, only the tags change
179
0
      esdR = (GF_ESDRemove *) com;
180
0
      esdR2 = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG);
181
0
      esdR2->ODID = esdR->ODID;
182
0
      esdR2->NbESDs = esdR->NbESDs;
183
      //alloc our stuff
184
0
      esdR2->ES_ID = (unsigned short*)gf_malloc(sizeof(u32) * esdR->NbESDs);
185
0
      if (!esdR2->ES_ID) {
186
0
        e = GF_OUT_OF_MEM;
187
0
        goto err_exit;
188
0
      }
189
0
      skipped = 0;
190
      //get the ES_ID in the mpod indicated in the ES_ID[]
191
0
      for (i = 0; i < esdR->NbESDs; i++) {
192
0
        if (!mpod->trackIDs || !esdR->ES_ID[i] || (esdR->ES_ID[i]>mpod->trackIDCount)) continue;
193
        //if the ref index is not valid, remove this desc...
194
0
        if (gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[esdR->ES_ID[i] - 1]) == NULL) {
195
0
          skipped ++;
196
0
        } else {
197
          //the command in the file has the ref index of the trackID in the mpod
198
0
          esdR2->ES_ID[i - skipped] = mpod->trackIDs[esdR->ES_ID[i] - 1];
199
0
        }
200
0
      }
201
      //gf_realloc...
202
0
      if (skipped && (skipped != esdR2->NbESDs) ) {
203
0
        esdR2->NbESDs -= skipped;
204
0
        esdR2->ES_ID = (unsigned short*)gf_realloc(esdR2->ES_ID, sizeof(u32) * esdR2->NbESDs);
205
0
      }
206
0
      gf_odf_com_del((GF_ODCom **)&esdR);
207
0
      gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdR2);
208
0
      break;
209
210
0
    default:
211
0
      e = gf_odf_codec_add_com(ODencode, com);
212
0
      if (e) goto err_exit;
213
0
    }
214
0
  }
215
  //encode our new AU
216
0
  e = gf_odf_codec_encode(ODencode, 1);
217
0
  if (e) goto err_exit;
218
219
  //and set the buffer in the sample
220
0
  gf_free(sample->data);
221
0
  sample->data = NULL;
222
0
  sample->dataLength = 0;
223
0
  e = gf_odf_codec_get_au(ODencode, &sample->data, &sample->dataLength);
224
225
0
err_exit:
226
0
  gf_odf_codec_del(ODdecode);
227
0
  gf_odf_codec_del(ODencode);
228
0
  return e;
229
0
}
230
231
232
// Update the dependencies when an OD AU is inserted in the file
233
GF_Err Media_ParseODFrame(GF_MediaBox *mdia, const GF_ISOSample *sample, GF_ISOSample **od_samp)
234
0
{
235
0
  GF_TrackReferenceBox *tref;
236
0
  GF_TrackReferenceTypeBox *mpod;
237
0
  GF_Err e;
238
0
  GF_ODCom *com;
239
0
  GF_ODCodec *ODencode;
240
0
  GF_ODCodec *ODdecode;
241
0
  u32 i, j;
242
  //the commands we proceed
243
0
  GF_ESDUpdate *esdU, *esdU2;
244
0
  GF_ESDRemove *esdR, *esdR2;
245
0
  GF_ODUpdate *odU, *odU2;
246
247
  //the desc they contain
248
0
  GF_ObjectDescriptor *od;
249
0
  GF_IsomObjectDescriptor *isom_od;
250
0
  GF_ESD *esd;
251
0
  GF_ES_ID_Ref *ref;
252
0
  GF_Descriptor *desc;
253
254
0
  *od_samp = NULL;
255
0
  if (!mdia || !sample || !sample->data || !sample->dataLength) return GF_BAD_PARAM;
256
257
  //First find the references, and create them if none
258
0
  tref = mdia->mediaTrack->References;
259
0
  if (!tref) {
260
0
    tref = (GF_TrackReferenceBox *) gf_isom_box_new_parent(&mdia->mediaTrack->child_boxes, GF_ISOM_BOX_TYPE_TREF);
261
0
    if (!tref) return GF_OUT_OF_MEM;
262
0
    e = trak_on_child_box((GF_Box*)mdia->mediaTrack, (GF_Box *) tref, GF_FALSE);
263
0
    if (e) return e;
264
0
  }
265
  //then find the OD reference, and create it if none
266
0
  e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
267
0
  if (e) return e;
268
0
  if (!mpod) {
269
0
    mpod = (GF_TrackReferenceTypeBox *) gf_isom_box_new_parent(&tref->child_boxes, GF_ISOM_BOX_TYPE_REFT);
270
0
    if (!mpod) return GF_OUT_OF_MEM;
271
0
    mpod->reference_type = GF_ISOM_BOX_TYPE_MPOD;
272
0
  }
273
274
  //OK, create our codecs
275
0
  ODencode = gf_odf_codec_new();
276
0
  if (!ODencode) return GF_OUT_OF_MEM;
277
0
  ODdecode = gf_odf_codec_new();
278
0
  if (!ODdecode) return GF_OUT_OF_MEM;
279
280
0
  e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
281
0
  if (e) goto err_exit;
282
0
  e = gf_odf_codec_decode(ODdecode);
283
0
  if (e) goto err_exit;
284
285
0
  while (1) {
286
0
    com = gf_odf_codec_get_com(ODdecode);
287
0
    if (!com) break;
288
289
    //check our commands
290
0
    switch (com->tag) {
291
    //Rewrite OD Update
292
0
    case GF_ODF_OD_UPDATE_TAG:
293
      //duplicate our command
294
0
      odU = (GF_ODUpdate *) com;
295
0
      odU2 = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
296
297
0
      i=0;
298
0
      while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
299
        //both OD and IODs are accepted
300
0
        switch (desc->tag) {
301
0
        case GF_ODF_OD_TAG:
302
0
        case GF_ODF_IOD_TAG:
303
0
          break;
304
0
        default:
305
0
          e = GF_ODF_INVALID_DESCRIPTOR;
306
0
          goto err_exit;
307
0
        }
308
        //get the esd
309
0
        e = gf_odf_desc_copy(desc, (GF_Descriptor **)&od);
310
0
        if (e) goto err_exit;
311
0
        if (desc->tag == GF_ODF_OD_TAG) {
312
0
          isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomObjectDescriptor));
313
0
          if (!isom_od) return GF_OUT_OF_MEM;
314
0
          isom_od->tag = GF_ODF_ISOM_OD_TAG;
315
0
        } else {
316
0
          isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomInitialObjectDescriptor));
317
0
          if (!isom_od) return GF_OUT_OF_MEM;
318
0
          isom_od->tag = GF_ODF_ISOM_IOD_TAG;
319
          //copy PL
320
0
          ((GF_IsomInitialObjectDescriptor *)isom_od)->inlineProfileFlag = ((GF_InitialObjectDescriptor *)od)->inlineProfileFlag;
321
0
          ((GF_IsomInitialObjectDescriptor *)isom_od)->graphics_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->graphics_profileAndLevel;
322
0
          ((GF_IsomInitialObjectDescriptor *)isom_od)->audio_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->audio_profileAndLevel;
323
0
          ((GF_IsomInitialObjectDescriptor *)isom_od)->OD_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->OD_profileAndLevel;
324
0
          ((GF_IsomInitialObjectDescriptor *)isom_od)->scene_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->scene_profileAndLevel;
325
0
          ((GF_IsomInitialObjectDescriptor *)isom_od)->visual_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->visual_profileAndLevel;
326
0
          ((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList = ((GF_InitialObjectDescriptor *)od)->IPMPToolList;
327
0
          ((GF_InitialObjectDescriptor *)od)->IPMPToolList = NULL;
328
0
        }
329
        //in OD stream only ref desc are accepted
330
0
        isom_od->ES_ID_RefDescriptors = gf_list_new();
331
0
        isom_od->ES_ID_IncDescriptors = NULL;
332
333
        //TO DO: check that a given sampleDescription exists
334
0
        isom_od->extensionDescriptors = od->extensionDescriptors;
335
0
        od->extensionDescriptors = NULL;
336
0
        isom_od->IPMP_Descriptors = od->IPMP_Descriptors;
337
0
        od->IPMP_Descriptors = NULL;
338
0
        isom_od->OCIDescriptors = od->OCIDescriptors;
339
0
        od->OCIDescriptors = NULL;
340
0
        isom_od->URLString = od->URLString;
341
0
        od->URLString = NULL;
342
0
        isom_od->objectDescriptorID = od->objectDescriptorID;
343
344
0
        j=0;
345
0
        while ((esd = (GF_ESD*)gf_list_enum(od->ESDescriptors, &j))) {
346
0
          ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG);
347
0
          if (!esd->ESID) {
348
0
            GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[ISOM] Missing ESID on ESD, cannot add track reference in OD frame"));
349
0
            e = GF_BAD_PARAM;
350
0
            goto err_exit;
351
0
          }
352
          //1 to 1 mapping trackID and ESID. Add this track to MPOD
353
          //if track does not exist, this will be remove while reading the OD stream
354
0
          e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
355
0
          if (e) goto err_exit;
356
0
          e = gf_odf_desc_add_desc((GF_Descriptor *)isom_od, (GF_Descriptor *)ref);
357
0
          if (e) goto err_exit;
358
0
        }
359
        //delete our desc
360
0
        gf_odf_desc_del((GF_Descriptor *)od);
361
        //and add the new one to our command
362
0
        gf_list_add(odU2->objectDescriptors, isom_od);
363
0
      }
364
      //delete the command
365
0
      gf_odf_com_del((GF_ODCom **)&odU);
366
      //and add the new one to the codec
367
0
      gf_odf_codec_add_com(ODencode, (GF_ODCom *)odU2);
368
0
      break;
369
370
    //Rewrite ESD Update
371
0
    case GF_ODF_ESD_UPDATE_TAG:
372
0
      esdU = (GF_ESDUpdate *) com;
373
0
      esdU2 = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG);
374
0
      esdU2->ODID = esdU->ODID;
375
0
      i=0;
376
0
      while ((esd = (GF_ESD*)gf_list_enum(esdU->ESDescriptors, &i))) {
377
0
        ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG);
378
        //1 to 1 mapping trackID and ESID
379
0
        e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
380
0
        if (e) goto err_exit;
381
0
        e = gf_list_add(esdU2->ESDescriptors, ref);
382
0
        if (e) goto err_exit;
383
0
      }
384
0
      gf_odf_com_del((GF_ODCom **)&esdU);
385
0
      gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdU2);
386
0
      break;
387
388
    //Brand new case: the ESRemove has to be rewritten too according to the specs...
389
0
    case GF_ODF_ESD_REMOVE_TAG:
390
0
      esdR = (GF_ESDRemove *) com;
391
0
      esdR2 = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG);
392
      //change the tag for the file format
393
0
      esdR2->tag = GF_ODF_ESD_REMOVE_REF_TAG;
394
0
      esdR2->ODID = esdR->ODID;
395
0
      esdR2->NbESDs = esdR->NbESDs;
396
0
      if (esdR->NbESDs) {
397
        //alloc our stuff
398
0
        esdR2->ES_ID = (unsigned short*)gf_malloc(sizeof(u32) * esdR->NbESDs);
399
0
        if (!esdR2->ES_ID) {
400
0
          e = GF_OUT_OF_MEM;
401
0
          goto err_exit;
402
0
        }
403
0
        for (i = 0; i < esdR->NbESDs; i++) {
404
          //1 to 1 mapping trackID and ESID
405
0
          e = reftype_AddRefTrack(mpod, esdR->ES_ID[i], &esdR2->ES_ID[i]);
406
0
          if (e) goto err_exit;
407
0
        }
408
0
      }
409
0
      gf_odf_com_del(&com);
410
0
      gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdR2);
411
0
      break;
412
413
    //Add the command as is
414
0
    default:
415
0
      e = gf_odf_codec_add_com(ODencode, com);
416
0
      if (e) goto err_exit;
417
0
    }
418
0
  }
419
420
  //encode our new AU
421
0
  e = gf_odf_codec_encode(ODencode, 1);
422
0
  if (e) goto err_exit;
423
424
  //and set the buffer in the sample
425
0
  *od_samp = gf_isom_sample_new();
426
0
  (*od_samp)->CTS_Offset = sample->CTS_Offset;
427
0
  (*od_samp)->DTS = sample->DTS;
428
0
  (*od_samp)->IsRAP = sample->IsRAP;
429
0
  e = gf_odf_codec_get_au(ODencode, & (*od_samp)->data, & (*od_samp)->dataLength);
430
0
  if (e) {
431
0
    gf_isom_sample_del(od_samp);
432
0
    *od_samp = NULL;
433
0
  }
434
435
0
err_exit:
436
437
0
  gf_odf_codec_del(ODencode);
438
0
  gf_odf_codec_del(ODdecode);
439
0
  return e;
440
0
}
441
442
443
444
// Rewrite the good dependencies when an OD AU is extracted from the file
445
static u32 Media_FindOD_ID(GF_MediaBox *mdia, GF_ISOSample *sample, u32 track_id)
446
0
{
447
0
  GF_Err e;
448
0
  GF_ODCodec *ODdecode;
449
0
  GF_ODCom *com;
450
0
  u32 the_od_id;
451
0
  GF_ODUpdate *odU;
452
0
  GF_ESD *esd;
453
0
  GF_Descriptor *desc;
454
0
  GF_TrackReferenceTypeBox *mpod;
455
0
  u32 i, j;
456
457
0
  if (!mdia || !sample || !sample->data || !sample->dataLength) return 0;
458
459
0
  mpod = NULL;
460
0
  e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
461
0
  if (e) return 0;
462
  //no references, nothing to do...
463
0
  if (!mpod) return 0;
464
465
0
  the_od_id = 0;
466
467
0
  ODdecode = gf_odf_codec_new();
468
0
  if (!ODdecode) return 0;
469
0
  e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
470
0
  if (e) goto err_exit;
471
0
  e = gf_odf_codec_decode(ODdecode);
472
0
  if (e) goto err_exit;
473
474
0
  while (1) {
475
0
    GF_List *esd_list = NULL;
476
0
    com = gf_odf_codec_get_com(ODdecode);
477
0
    if (!com) break;
478
0
    if (com->tag != GF_ODF_OD_UPDATE_TAG) continue;
479
0
    odU = (GF_ODUpdate *) com;
480
481
0
    i=0;
482
0
    while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
483
0
      switch (desc->tag) {
484
0
      case GF_ODF_OD_TAG:
485
0
      case GF_ODF_IOD_TAG:
486
0
        esd_list = ((GF_ObjectDescriptor *)desc)->ESDescriptors;
487
0
        break;
488
0
      default:
489
0
        continue;
490
0
      }
491
0
      j=0;
492
0
      while ((esd = (GF_ESD*)gf_list_enum( esd_list, &j))) {
493
0
        if (esd->ESID==track_id) {
494
0
          the_od_id = ((GF_IsomObjectDescriptor*)desc)->objectDescriptorID;
495
0
          break;
496
0
        }
497
0
      }
498
0
      if (the_od_id) break;
499
0
    }
500
0
    gf_odf_com_del((GF_ODCom **)&odU);
501
0
    if (the_od_id) break;
502
0
  }
503
504
0
err_exit:
505
0
  gf_odf_codec_del(ODdecode);
506
0
  return the_od_id; //still 0 if error, no need to check for e
507
0
}
508
509
510
GF_EXPORT
511
u32 gf_isom_find_od_id_for_track(GF_ISOFile *file, u32 track)
512
0
{
513
0
  u32 i, j, di, the_od_id;
514
0
  GF_TrackBox *od_tk;
515
0
  GF_TrackBox *tk = gf_isom_get_track_box(file, track);
516
0
  if (!tk) return 0;
517
518
0
  i=0;
519
0
  while ( (od_tk = (GF_TrackBox*)gf_list_enum(file->moov->trackList, &i))) {
520
0
    if (!od_tk || !od_tk->Media || !od_tk->Media->handler  || !od_tk->Media->information ||
521
0
      !od_tk->Media->information->sampleTable || !od_tk->Media->information->sampleTable->SampleSize ) {
522
523
0
      continue;
524
0
    }
525
526
527
0
    if (od_tk->Media->handler->handlerType != GF_ISOM_MEDIA_OD) continue;
528
529
0
    for (j=0; j<od_tk->Media->information->sampleTable->SampleSize->sampleCount; j++) {
530
0
      GF_ISOSample *samp = gf_isom_get_sample(file, i, j+1, &di);
531
0
      the_od_id = Media_FindOD_ID(od_tk->Media, samp, tk->Header->trackID);
532
0
      gf_isom_sample_del(&samp);
533
0
      if (the_od_id) return the_od_id;
534
0
    }
535
0
  }
536
0
  return 0;
537
0
}
538
539
#endif /*GPAC_DISABLE_ISOM*/