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