Line data Source code
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 417 : GF_ODCodec *gf_odf_codec_new()
34 : {
35 : GF_ODCodec *codec;
36 : GF_List *comList;
37 :
38 417 : comList = gf_list_new();
39 417 : if (!comList) return NULL;
40 :
41 417 : codec = (GF_ODCodec *) gf_malloc(sizeof(GF_ODCodec));
42 417 : if (!codec) {
43 0 : gf_list_del(comList);
44 0 : return NULL;
45 : }
46 : //the bitstream is always NULL. It is created on the fly for access unit processing only
47 417 : codec->bs = NULL;
48 417 : codec->CommandList = comList;
49 417 : return codec;
50 : }
51 :
52 : GF_EXPORT
53 417 : void gf_odf_codec_del(GF_ODCodec *codec)
54 : {
55 417 : if (!codec) return;
56 :
57 424 : while (gf_list_count(codec->CommandList)) {
58 7 : GF_ODCom *com = (GF_ODCom *)gf_list_get(codec->CommandList, 0);
59 7 : gf_odf_delete_command(com);
60 7 : gf_list_rem(codec->CommandList, 0);
61 : }
62 417 : gf_list_del(codec->CommandList);
63 417 : if (codec->bs) gf_bs_del(codec->bs);
64 417 : gf_free(codec);
65 : }
66 :
67 :
68 : /************************************************************
69 : Codec Encoder Functions
70 : ************************************************************/
71 :
72 : GF_EXPORT
73 231 : GF_Err gf_odf_codec_add_com(GF_ODCodec *codec, GF_ODCom *command)
74 : {
75 231 : if (!codec || !command) return GF_BAD_PARAM;
76 231 : return gf_list_add(codec->CommandList, command);
77 : }
78 :
79 : GF_EXPORT
80 238 : GF_Err gf_odf_codec_encode(GF_ODCodec *codec, u32 cleanup_type)
81 : {
82 : GF_ODCom *com;
83 : GF_Err e = GF_OK;
84 : u32 i;
85 :
86 238 : 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 238 : if (codec->bs) return GF_BAD_PARAM;
91 238 : codec->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
92 238 : if (!codec->bs) return GF_OUT_OF_MEM;
93 :
94 : /*encode each command*/
95 238 : i = 0;
96 714 : while ((com = (GF_ODCom *)gf_list_enum(codec->CommandList, &i))) {
97 238 : e = gf_odf_write_command(codec->bs, com);
98 238 : if (e) goto err_exit;
99 : //don't forget OD Commands are aligned...
100 238 : gf_bs_align(codec->bs);
101 : }
102 :
103 : //if an error occurs, delete the GF_BitStream and empty the codec
104 238 : err_exit:
105 238 : if (e) {
106 0 : gf_bs_del(codec->bs);
107 0 : codec->bs = NULL;
108 : }
109 238 : if (cleanup_type==1) {
110 356 : while (gf_list_count(codec->CommandList)) {
111 178 : com = (GF_ODCom *)gf_list_get(codec->CommandList, 0);
112 178 : gf_odf_delete_command(com);
113 178 : gf_list_rem(codec->CommandList, 0);
114 : }
115 : }
116 238 : if (cleanup_type==0) {
117 54 : gf_list_reset(codec->CommandList);
118 : }
119 : return e;
120 : }
121 :
122 : GF_EXPORT
123 238 : GF_Err gf_odf_codec_get_au(GF_ODCodec *codec, u8 **outAU, u32 *au_length)
124 : {
125 238 : if (!codec || !codec->bs || !outAU || *outAU) return GF_BAD_PARAM;
126 238 : gf_bs_get_content(codec->bs, outAU, au_length);
127 238 : gf_bs_del(codec->bs);
128 238 : codec->bs = NULL;
129 238 : return GF_OK;
130 : }
131 :
132 :
133 :
134 : /************************************************************
135 : Codec Decoder Functions
136 : ************************************************************/
137 :
138 : GF_EXPORT
139 249 : GF_Err gf_odf_codec_set_au(GF_ODCodec *codec, const u8 *au, u32 au_length)
140 : {
141 249 : if (!codec ) return GF_BAD_PARAM;
142 249 : if (!au || !au_length) return GF_OK;
143 :
144 : //if the command list is not empty, this is an error
145 249 : if (gf_list_count(codec->CommandList)) return GF_BAD_PARAM;
146 :
147 : //the bitStream should not be here
148 249 : if (codec->bs) return GF_BAD_PARAM;
149 :
150 249 : codec->bs = gf_bs_new(au, (u64) au_length, (unsigned char)GF_BITSTREAM_READ);
151 249 : if (!codec->bs) return GF_OUT_OF_MEM;
152 249 : return GF_OK;
153 : }
154 :
155 :
156 : GF_EXPORT
157 249 : GF_Err gf_odf_codec_decode(GF_ODCodec *codec)
158 : {
159 : GF_Err e = GF_OK;
160 : u32 size = 0, comSize, bufSize;
161 : GF_ODCom *com;
162 :
163 249 : if (!codec || !codec->bs) return GF_BAD_PARAM;
164 :
165 249 : bufSize = (u32) gf_bs_available(codec->bs);
166 747 : while (size < bufSize) {
167 249 : e = gf_odf_parse_command(codec->bs, &com, &comSize);
168 249 : if (e) goto err_exit;
169 249 : gf_list_add(codec->CommandList, com);
170 249 : size += comSize + gf_odf_size_field_size(comSize);
171 : //OD Commands are aligned
172 249 : gf_bs_align(codec->bs);
173 : }
174 : //then delete our bitstream
175 249 : gf_bs_del(codec->bs);
176 249 : codec->bs = NULL;
177 249 : if (size != bufSize) {
178 : e = GF_ODF_INVALID_COMMAND;
179 : goto err_exit;
180 : }
181 : 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 : }
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 : }
193 : return e;
194 : }
195 :
196 : //get the first command in the codec and remove the entry
197 : GF_EXPORT
198 490 : GF_ODCom *gf_odf_codec_get_com(GF_ODCodec *codec)
199 : {
200 : GF_ODCom *com;
201 490 : if (!codec || codec->bs) return NULL;
202 490 : com = (GF_ODCom*)gf_list_get(codec->CommandList, 0);
203 490 : if (com) gf_list_rem(codec->CommandList, 0);
204 : return com;
205 : }
206 :
207 :
208 :
209 : /************************************************************
210 : OD Commands Functions
211 : ************************************************************/
212 :
213 : //some easy way to get an OD GF_ODCom...
214 : GF_EXPORT
215 354 : GF_ODCom *gf_odf_com_new(u8 tag)
216 : {
217 : GF_ODCom *newcom;
218 :
219 354 : newcom = gf_odf_create_command(tag);
220 354 : newcom->tag = tag;
221 354 : return (GF_ODCom *)newcom;
222 : }
223 :
224 : // ... and to delete it
225 : GF_EXPORT
226 418 : GF_Err gf_odf_com_del(GF_ODCom **com)
227 : {
228 : GF_Err e;
229 418 : e = gf_odf_delete_command(*com);
230 418 : *com = NULL;
231 418 : return e;
232 : }
233 :
234 :
235 : /************************************************************
236 : Object Descriptors Functions
237 : ************************************************************/
238 :
239 : //some easy way to get an mpeg4 descriptor ...
240 : GF_EXPORT
241 14774 : GF_Descriptor *gf_odf_desc_new(u8 tag)
242 : {
243 : GF_Descriptor *newdesc;
244 14774 : newdesc = gf_odf_create_descriptor(tag);
245 14774 : newdesc->tag = tag;
246 14774 : return (GF_Descriptor *)newdesc;
247 : }
248 :
249 : // ... and to delete it
250 : GF_EXPORT
251 10992 : void gf_odf_desc_del(GF_Descriptor *desc)
252 : {
253 10992 : if (desc) gf_odf_delete_descriptor(desc);
254 10992 : }
255 :
256 : //this functions will destroy the descriptors in a list but not the list
257 : GF_EXPORT
258 12 : GF_Err gf_odf_desc_list_del(GF_List *descList)
259 : {
260 : GF_Err e;
261 :
262 12 : if (! descList) return GF_BAD_PARAM;
263 :
264 18 : while (gf_list_count(descList)) {
265 6 : GF_Descriptor *tmp = (GF_Descriptor*)gf_list_get(descList, 0);
266 6 : gf_list_rem(descList, 0);
267 6 : e = gf_odf_delete_descriptor(tmp);
268 6 : if (e) return e;
269 : }
270 : return GF_OK;
271 : }
272 :
273 :
274 :
275 : GF_EXPORT
276 3580 : GF_ESD *gf_odf_desc_esd_new(u32 sl_predefined)
277 : {
278 : GF_ESD *esd;
279 3580 : esd = (GF_ESD *) gf_odf_desc_new(GF_ODF_ESD_TAG);
280 3580 : esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG);
281 3580 : esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
282 3580 : esd->slConfig = (GF_SLConfig *) gf_odf_new_slc((u8) sl_predefined);
283 3580 : return esd;
284 : }
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 5288 : GF_Err gf_odf_desc_read(u8 *raw_desc, u32 descSize, GF_Descriptor **outDesc)
291 : {
292 : GF_Err e;
293 : u32 size;
294 : GF_BitStream *bs;
295 5288 : if (!raw_desc || !descSize) return GF_BAD_PARAM;
296 :
297 5288 : bs = gf_bs_new(raw_desc, (u64) descSize, GF_BITSTREAM_READ);
298 5288 : if (!bs) return GF_OUT_OF_MEM;
299 :
300 5288 : size = 0;
301 5288 : e = gf_odf_parse_descriptor(bs, outDesc, &size);
302 : //the size dosn't have the header in it
303 5288 : 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 5288 : gf_bs_del(bs);
313 5288 : return e;
314 : }
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 4979 : GF_Err gf_odf_desc_write_bs(GF_Descriptor *desc, GF_BitStream *bs)
320 : {
321 : GF_Err e;
322 4979 : if (!desc || !bs) return GF_BAD_PARAM;
323 :
324 : //then encode our desc...
325 4979 : e = gf_odf_write_descriptor(bs, desc);
326 4979 : if (e) return e;
327 :
328 4979 : return GF_OK;
329 : }
330 :
331 : GF_EXPORT
332 4981 : GF_Err gf_odf_desc_write(GF_Descriptor *desc, u8 **outEncDesc, u32 *outSize)
333 : {
334 : GF_Err e;
335 : GF_BitStream *bs;
336 4981 : if (!desc || !outEncDesc || !outSize) return GF_BAD_PARAM;
337 4979 : *outEncDesc = NULL;
338 4979 : *outSize = 0;
339 :
340 4979 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
341 4979 : if (!bs) return GF_OUT_OF_MEM;
342 :
343 4979 : e = gf_odf_desc_write_bs(desc, bs);
344 :
345 : //then get the content from our bitstream
346 4979 : gf_bs_get_content(bs, outEncDesc, outSize);
347 4979 : gf_bs_del(bs);
348 4979 : return e;
349 : }
350 :
351 :
352 : //use this function to get the size of a standalone descriptor
353 : GF_EXPORT
354 3808 : u32 gf_odf_desc_size(GF_Descriptor *desc)
355 : {
356 : u32 descSize;
357 : GF_Err e;
358 :
359 3808 : if (!desc) return GF_BAD_PARAM;
360 : //get the descriptor length
361 3806 : e = gf_odf_size_descriptor(desc, &descSize);
362 3806 : if (e) return 0;
363 : //add the header length
364 3806 : descSize += gf_odf_size_field_size(descSize);
365 3806 : return descSize;
366 :
367 : }
368 :
369 : //this is useful to duplicate on the fly a descriptor (mainly for authoring purposes)
370 : GF_EXPORT
371 3435 : GF_Err gf_odf_desc_copy(GF_Descriptor *inDesc, GF_Descriptor **outDesc)
372 : {
373 : GF_Err e;
374 : u8 *desc;
375 : u32 size, oti=0;
376 :
377 : //patch for esd copy, we now signal codecid (32 bit) in OTI (8 bits)
378 3435 : if (inDesc->tag == GF_ODF_ESD_TAG) {
379 : GF_ESD *esd = (GF_ESD *)inDesc;
380 2377 : if (esd->decoderConfig) {
381 2377 : oti = esd->decoderConfig->objectTypeIndication;
382 2377 : esd->decoderConfig->objectTypeIndication = 0;
383 : }
384 : }
385 :
386 : //warning: here we get some data allocated
387 3435 : e = gf_odf_desc_write(inDesc, &desc, &size);
388 3435 : if (e) return e;
389 3435 : e = gf_odf_desc_read(desc, size, outDesc);
390 3435 : gf_free(desc);
391 3435 : if (oti && !e) {
392 : GF_ESD *esd = (GF_ESD *)inDesc;
393 2305 : GF_ESD *out_esd = (GF_ESD *)*outDesc;
394 2305 : if (esd->decoderConfig) esd->decoderConfig->objectTypeIndication = oti;
395 2305 : if (out_esd->decoderConfig) out_esd->decoderConfig->objectTypeIndication = oti;
396 : }
397 : return e;
398 : }
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 2243 : GF_Err gf_odf_desc_add_desc(GF_Descriptor *parentDesc, GF_Descriptor *newDesc)
409 : {
410 : GF_DecoderConfig *dcd;
411 :
412 : //our ADD definition
413 : GF_Err AddDescriptorToOD(GF_ObjectDescriptor *od, GF_Descriptor *desc);
414 : GF_Err AddDescriptorToIOD(GF_InitialObjectDescriptor *iod, GF_Descriptor *desc);
415 : GF_Err AddDescriptorToESD(GF_ESD *esd, GF_Descriptor *desc);
416 : GF_Err AddDescriptorToIsomIOD(GF_IsomInitialObjectDescriptor *iod, GF_Descriptor *desc);
417 : GF_Err AddDescriptorToIsomOD(GF_IsomObjectDescriptor *od, GF_Descriptor *desc);
418 :
419 2243 : if (!parentDesc || !newDesc) return GF_BAD_PARAM;
420 :
421 2243 : switch (parentDesc->tag) {
422 : //these are container descriptors
423 315 : case GF_ODF_OD_TAG:
424 315 : return AddDescriptorToOD((GF_ObjectDescriptor *)parentDesc, newDesc);
425 521 : case GF_ODF_IOD_TAG:
426 521 : return AddDescriptorToIOD((GF_InitialObjectDescriptor *)parentDesc, newDesc);
427 780 : case GF_ODF_ESD_TAG:
428 780 : return AddDescriptorToESD((GF_ESD *)parentDesc, newDesc);
429 415 : case GF_ODF_DCD_TAG:
430 : dcd = (GF_DecoderConfig *)parentDesc;
431 830 : if ((newDesc->tag == GF_ODF_DSI_TAG)
432 415 : || (newDesc->tag == GF_ODF_BIFS_CFG_TAG)
433 33 : || (newDesc->tag == GF_ODF_UI_CFG_TAG)
434 0 : || (newDesc->tag == GF_ODF_TEXT_CFG_TAG)
435 : ) {
436 415 : if (dcd->decoderSpecificInfo) return GF_ODF_FORBIDDEN_DESCRIPTOR;
437 415 : dcd->decoderSpecificInfo = (GF_DefaultDescriptor *) newDesc;
438 415 : return GF_OK;
439 0 : } else if (newDesc->tag == GF_ODF_EXT_PL_TAG) {
440 0 : return gf_list_add(dcd->profileLevelIndicationIndexDescriptor, newDesc);
441 : }
442 : 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 : case GF_ODF_QOS_TAG:
449 : return GF_BAD_PARAM;
450 :
451 : //MP4 File Format tags
452 64 : case GF_ODF_ISOM_IOD_TAG:
453 64 : return AddDescriptorToIsomIOD((GF_IsomInitialObjectDescriptor *)parentDesc, newDesc);
454 148 : case GF_ODF_ISOM_OD_TAG:
455 148 : 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 : {
463 : 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 : }
468 0 : default:
469 0 : return GF_ODF_FORBIDDEN_DESCRIPTOR;
470 : }
471 : }
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 5 : GF_Err gf_odf_desc_list_read(u8 *raw_list, u32 raw_size, GF_List *descList)
488 : {
489 : GF_BitStream *bs;
490 : u32 size, desc_size;
491 : GF_Descriptor *desc;
492 : GF_Err e = GF_OK;
493 :
494 5 : if (!descList || !raw_list || !raw_size) return GF_BAD_PARAM;
495 :
496 5 : bs = gf_bs_new(raw_list, raw_size, GF_BITSTREAM_READ);
497 5 : if (!bs) return GF_OUT_OF_MEM;
498 :
499 : size = 0;
500 10 : while (size < raw_size) {
501 5 : e = gf_odf_parse_descriptor(bs, &desc, &desc_size);
502 5 : if (e) goto exit;
503 5 : gf_list_add(descList, desc);
504 5 : size += desc_size + gf_odf_size_field_size(desc_size);
505 : }
506 :
507 5 : exit:
508 : //then delete our bitstream
509 5 : gf_bs_del(bs);
510 5 : if (size != raw_size) e = GF_ODF_INVALID_DESCRIPTOR;
511 : return e;
512 : }
513 :
514 :
515 : GF_EXPORT
516 2 : GF_Err gf_odf_desc_list_write(GF_List *descList, u8 **outEncList, u32 *outSize)
517 : {
518 : GF_BitStream *bs;
519 : GF_Err e;
520 :
521 2 : if (!descList || !outEncList || *outEncList || !outSize) return GF_BAD_PARAM;
522 :
523 2 : *outSize = 0;
524 :
525 2 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
526 2 : if (!bs) return GF_OUT_OF_MEM;
527 :
528 2 : e = gf_odf_write_descriptor_list(bs, descList);
529 2 : if (e) {
530 0 : gf_bs_del(bs);
531 0 : return e;
532 : }
533 :
534 2 : gf_bs_get_content(bs, outEncList, outSize);
535 2 : gf_bs_del(bs);
536 2 : return GF_OK;
537 : }
538 :
539 : GF_EXPORT
540 4 : GF_Err gf_odf_desc_list_size(GF_List *descList, u32 *outSize)
541 : {
542 4 : return gf_odf_size_descriptor_list(descList, outSize);
543 : }
544 :
545 :
546 :
547 26 : GF_Err gf_odf_codec_apply_com(GF_ODCodec *codec, GF_ODCom *command)
548 : {
549 : GF_ODCom *com;
550 : GF_ODUpdate *odU, *odU_o;
551 : u32 i, count;
552 26 : count = gf_list_count(codec->CommandList);
553 :
554 26 : switch (command->tag) {
555 : case GF_ODF_OD_REMOVE_TAG:
556 6 : for (i=0; i<count; i++) {
557 6 : com = (GF_ODCom *)gf_list_get(codec->CommandList, i);
558 : /*process OD updates*/
559 6 : if (com->tag==GF_ODF_OD_UPDATE_TAG) {
560 : u32 count2, j, k;
561 : GF_ODRemove *odR = (GF_ODRemove *) command;
562 : odU = (GF_ODUpdate *)com;
563 6 : count2 = gf_list_count(odU->objectDescriptors);
564 : /*remove all descs*/
565 24 : for (k=0; k<count2; k++) {
566 18 : GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k);
567 30 : for (j=0; j<odR->NbODs; j++) {
568 18 : if (od->objectDescriptorID==odR->OD_ID[j]) {
569 6 : gf_list_rem(odU->objectDescriptors, k);
570 6 : k--;
571 6 : count2--;
572 6 : gf_odf_desc_del((GF_Descriptor *)od);
573 6 : break;
574 : }
575 : }
576 : }
577 6 : if (!gf_list_count(odU->objectDescriptors)) {
578 0 : gf_list_rem(codec->CommandList, i);
579 0 : i--;
580 0 : count--;
581 : }
582 : }
583 : /*process ESD updates*/
584 0 : else if (com->tag==GF_ODF_ESD_UPDATE_TAG) {
585 : u32 j;
586 : 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 : }
596 : }
597 : }
598 : /*process ESD remove*/
599 0 : else if (com->tag==GF_ODF_ESD_REMOVE_TAG) {
600 : u32 j;
601 : 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 : }
611 : }
612 : }
613 : }
614 : return GF_OK;
615 : case GF_ODF_OD_UPDATE_TAG:
616 : odU_o = NULL;
617 0 : for (i=0; i<count; i++) {
618 6 : odU_o = (GF_ODUpdate*)gf_list_get(codec->CommandList, i);
619 : /*process OD updates*/
620 6 : if (odU_o->tag==GF_ODF_OD_UPDATE_TAG) break;
621 : odU_o = NULL;
622 : }
623 12 : if (!odU_o) {
624 6 : odU_o = (GF_ODUpdate *)gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
625 6 : gf_list_add(codec->CommandList, odU_o);
626 : }
627 : odU = (GF_ODUpdate*)command;
628 12 : count = gf_list_count(odU->objectDescriptors);
629 36 : for (i=0; i<count; i++) {
630 : Bool found = GF_FALSE;
631 24 : GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, i);
632 24 : u32 j, count2 = gf_list_count(odU_o->objectDescriptors);
633 42 : for (j=0; j<count2; j++) {
634 24 : GF_ObjectDescriptor *od2 = (GF_ObjectDescriptor *)gf_list_get(odU_o->objectDescriptors, j);
635 24 : if (od2->objectDescriptorID==od->objectDescriptorID) {
636 : found = GF_TRUE;
637 : break;
638 : }
639 : }
640 24 : if (!found) {
641 : GF_ObjectDescriptor *od_new;
642 18 : GF_Err e = gf_odf_desc_copy((GF_Descriptor*)od, (GF_Descriptor**)&od_new);
643 18 : if (e==GF_OK)
644 18 : gf_list_add(odU_o->objectDescriptors, od_new);
645 : }
646 :
647 : }
648 : return GF_OK;
649 : case GF_ODF_ESD_REMOVE_TAG:
650 6 : for (i=0; i<count; i++) {
651 6 : com = (GF_ODCom *)gf_list_get(codec->CommandList, i);
652 : /*process OD updates*/
653 6 : if (com->tag==GF_ODF_OD_UPDATE_TAG) {
654 : u32 count2, j, k, l;
655 : GF_ESDRemove *esdR = (GF_ESDRemove *) command;
656 : odU = (GF_ODUpdate *)com;
657 6 : count2 = gf_list_count(odU->objectDescriptors);
658 : /*remove all descs*/
659 24 : for (k=0; k<count2; k++) {
660 18 : GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k);
661 36 : for (j=0; j<gf_list_count(od->ESDescriptors); j++) {
662 18 : GF_ESD *esd = gf_list_get(od->ESDescriptors, j);
663 30 : for (l=0; l<esdR->NbESDs; l++) {
664 18 : if (esdR->ES_ID[l] == esd->ESID) {
665 6 : gf_list_rem(od->ESDescriptors, j);
666 6 : j--;
667 6 : gf_odf_desc_del((GF_Descriptor *)esd);
668 6 : break;
669 : }
670 : }
671 : }
672 : }
673 : }
674 : /*process ESD updates*/
675 0 : else if (com->tag==GF_ODF_ESD_UPDATE_TAG) {
676 : u32 j, k;
677 : 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 : }
687 : }
688 : }
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 : }
695 : }
696 : }
697 : return GF_OK;
698 : case GF_ODF_ESD_UPDATE_TAG:
699 2 : for (i=0; i<count; i++) {
700 2 : com = (GF_ODCom *)gf_list_get(codec->CommandList, i);
701 : /*process OD updates*/
702 2 : if (com->tag==GF_ODF_OD_UPDATE_TAG) {
703 : u32 count2, k, l;
704 : GF_ESDUpdate *esdU = (GF_ESDUpdate *) command;
705 : odU = (GF_ODUpdate *)com;
706 2 : count2 = gf_list_count(odU->objectDescriptors);
707 : /*remove all descs*/
708 2 : for (k=0; k<count2; k++) {
709 2 : GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k);
710 2 : if (od->objectDescriptorID==esdU->ODID) {
711 : GF_ESD *esd;
712 4 : while (gf_list_count(od->ESDescriptors)) {
713 2 : esd = gf_list_pop_back(od->ESDescriptors);
714 2 : gf_odf_desc_del((GF_Descriptor *)esd);
715 : }
716 2 : gf_list_transfer(od->ESDescriptors, esdU->ESDescriptors);
717 2 : l = 0;
718 4 : while ((esd = gf_list_enum(esdU->ESDescriptors, &l))) {
719 : 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 : }
724 : break;
725 : }
726 : }
727 : }
728 : /*process ESD updates*/
729 0 : else if (com->tag==GF_ODF_ESD_UPDATE_TAG) {
730 : return GF_NOT_SUPPORTED;
731 : }
732 : }
733 : return GF_OK;
734 : }
735 : return GF_NOT_SUPPORTED;
736 : }
|