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