Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Cyril Concolato / Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2005-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 : #include <gpac/constants.h>
28 :
29 : #ifndef GPAC_DISABLE_ISOM
30 :
31 281 : GF_Box *meta_box_new()
32 : {
33 562 : ISOM_DECL_BOX_ALLOC(GF_MetaBox, GF_ISOM_BOX_TYPE_META);
34 281 : tmp->child_boxes = gf_list_new();
35 281 : return (GF_Box *)tmp;
36 : }
37 :
38 281 : void meta_reset(GF_Box *s)
39 : {
40 : GF_MetaBox *ptr = (GF_MetaBox *)s;
41 281 : if (ptr == NULL) return;
42 :
43 : //destroy all boxes
44 281 : if (ptr->child_boxes) gf_isom_box_array_del(ptr->child_boxes);
45 281 : ptr->child_boxes = NULL;
46 :
47 : //reset pointers (destroyed above)
48 281 : ptr->handler = NULL;
49 281 : ptr->primary_resource = NULL;
50 281 : ptr->file_locations = NULL;
51 281 : ptr->item_locations = NULL;
52 281 : ptr->protections = NULL;
53 281 : ptr->item_infos = NULL;
54 281 : ptr->IPMP_control = NULL;
55 281 : ptr->item_refs = NULL;
56 281 : ptr->item_props = NULL;
57 281 : ptr->groups_list = NULL;
58 : }
59 :
60 281 : void meta_box_del(GF_Box *s)
61 : {
62 281 : meta_reset(s);
63 281 : gf_free(s);
64 281 : }
65 :
66 :
67 703 : GF_Err meta_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
68 : {
69 : GF_MetaBox *ptr = (GF_MetaBox *)s;
70 703 : switch (a->type) {
71 187 : case GF_ISOM_BOX_TYPE_HDLR:
72 187 : BOX_FIELD_ASSIGN(handler, GF_HandlerBox)
73 187 : break;
74 39 : case GF_ISOM_BOX_TYPE_PITM:
75 39 : BOX_FIELD_ASSIGN(primary_resource, GF_PrimaryItemBox)
76 39 : break;
77 0 : case GF_ISOM_BOX_TYPE_DINF:
78 0 : BOX_FIELD_ASSIGN(file_locations, GF_DataInformationBox)
79 0 : break;
80 68 : case GF_ISOM_BOX_TYPE_ILOC:
81 68 : BOX_FIELD_ASSIGN(item_locations, GF_ItemLocationBox)
82 68 : break;
83 23 : case GF_ISOM_BOX_TYPE_IPRO:
84 23 : BOX_FIELD_ASSIGN(protections, GF_ItemProtectionBox)
85 23 : break;
86 68 : case GF_ISOM_BOX_TYPE_IINF:
87 68 : BOX_FIELD_ASSIGN(item_infos, GF_ItemInfoBox)
88 68 : break;
89 25 : case GF_ISOM_BOX_TYPE_IREF:
90 25 : BOX_FIELD_ASSIGN(item_refs, GF_ItemReferenceBox);
91 25 : break;
92 53 : case GF_ISOM_BOX_TYPE_IPRP:
93 53 : BOX_FIELD_ASSIGN(item_props, GF_ItemPropertiesBox)
94 53 : break;
95 0 : case GF_ISOM_BOX_TYPE_GRPL:
96 0 : BOX_FIELD_ASSIGN(groups_list, GF_GroupListBox)
97 0 : break;
98 : }
99 : return GF_OK;
100 : }
101 :
102 188 : GF_Err meta_box_read(GF_Box *s, GF_BitStream *bs)
103 : {
104 188 : u64 pos = gf_bs_get_position(bs);
105 188 : u64 size = s->size;
106 188 : GF_Err e = gf_isom_box_array_read(s, bs);
107 : /*try to hack around QT files which don't use a full box for meta, rewind 4 bytes*/
108 188 : if (e && (pos>4) ) {
109 0 : gf_bs_seek(bs, pos-4);
110 0 : meta_reset(s);
111 0 : s->size = size+4;
112 0 : e = gf_isom_box_array_read(s, bs);
113 : }
114 188 : return e;
115 : }
116 :
117 : #ifndef GPAC_DISABLE_ISOM_WRITE
118 189 : GF_Err meta_box_write(GF_Box *s, GF_BitStream *bs)
119 : {
120 189 : return gf_isom_full_box_write(s, bs);
121 : }
122 :
123 449 : GF_Err meta_box_size(GF_Box *s)
124 : {
125 449 : u32 pos=0;
126 : GF_MetaBox *ptr = (GF_MetaBox *)s;
127 :
128 449 : gf_isom_check_position(s, (GF_Box *)ptr->handler, &pos);
129 449 : gf_isom_check_position(s, (GF_Box *)ptr->primary_resource, &pos);
130 449 : gf_isom_check_position(s, (GF_Box *)ptr->file_locations, &pos);
131 449 : gf_isom_check_position(s, (GF_Box *)ptr->item_locations, &pos);
132 449 : gf_isom_check_position(s, (GF_Box *)ptr->protections, &pos);
133 449 : gf_isom_check_position(s, (GF_Box *)ptr->item_infos, &pos);
134 449 : gf_isom_check_position(s, (GF_Box *)ptr->item_refs, &pos);
135 449 : gf_isom_check_position(s, (GF_Box *)ptr->item_props, &pos);
136 449 : gf_isom_check_position(s, (GF_Box *)ptr->groups_list, &pos);
137 449 : return GF_OK;
138 : }
139 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
140 :
141 8 : GF_Box *xml_box_new()
142 : {
143 16 : ISOM_DECL_BOX_ALLOC(GF_XMLBox, GF_ISOM_BOX_TYPE_XML);
144 8 : return (GF_Box *)tmp;
145 : }
146 :
147 8 : void xml_box_del(GF_Box *s)
148 : {
149 : GF_XMLBox *ptr = (GF_XMLBox *)s;
150 8 : if (ptr == NULL) return;
151 8 : if (ptr->xml) gf_free(ptr->xml);
152 8 : gf_free(ptr);
153 : }
154 :
155 3 : GF_Err xml_box_read(GF_Box *s, GF_BitStream *bs)
156 : {
157 : GF_XMLBox *ptr = (GF_XMLBox *)s;
158 3 : return gf_isom_read_null_terminated_string(s, bs, s->size, &ptr->xml);
159 : }
160 :
161 : #ifndef GPAC_DISABLE_ISOM_WRITE
162 4 : GF_Err xml_box_write(GF_Box *s, GF_BitStream *bs)
163 : {
164 : GF_Err e;
165 : GF_XMLBox *ptr = (GF_XMLBox *)s;
166 4 : if (!s) return GF_BAD_PARAM;
167 4 : e = gf_isom_full_box_write(s, bs);
168 4 : if (e) return e;
169 4 : if (ptr->xml) gf_bs_write_data(bs, ptr->xml, (u32) strlen(ptr->xml));
170 4 : gf_bs_write_u8(bs, 0);
171 4 : return GF_OK;
172 : }
173 :
174 10 : GF_Err xml_box_size(GF_Box *s)
175 : {
176 : GF_XMLBox *ptr = (GF_XMLBox *)s;
177 10 : if (!s) return GF_BAD_PARAM;
178 10 : ptr->size += (ptr->xml ? strlen(ptr->xml) : 0) + 1;
179 10 : return GF_OK;
180 : }
181 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
182 :
183 3 : GF_Box *bxml_box_new()
184 : {
185 6 : ISOM_DECL_BOX_ALLOC(GF_BinaryXMLBox, GF_ISOM_BOX_TYPE_BXML);
186 3 : return (GF_Box *)tmp;
187 : }
188 :
189 3 : void bxml_box_del(GF_Box *s)
190 : {
191 : GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s;
192 3 : if (ptr == NULL) return;
193 3 : if (ptr->data) gf_free(ptr->data);
194 3 : gf_free(ptr);
195 : }
196 :
197 1 : GF_Err bxml_box_read(GF_Box *s, GF_BitStream *bs)
198 : {
199 : GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s;
200 :
201 1 : ptr->data_length = (u32)(ptr->size);
202 1 : ptr->data = (char*)gf_malloc(sizeof(char)*ptr->data_length);
203 1 : if (!ptr->data) return GF_OUT_OF_MEM;
204 1 : gf_bs_read_data(bs, ptr->data, ptr->data_length);
205 1 : return GF_OK;
206 : }
207 :
208 : #ifndef GPAC_DISABLE_ISOM_WRITE
209 1 : GF_Err bxml_box_write(GF_Box *s, GF_BitStream *bs)
210 : {
211 : GF_Err e;
212 : GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s;
213 1 : if (!s) return GF_BAD_PARAM;
214 1 : e = gf_isom_full_box_write(s, bs);
215 1 : if (e) return e;
216 1 : if (ptr->data_length) gf_bs_write_data(bs, ptr->data, ptr->data_length);
217 : return GF_OK;
218 : }
219 :
220 1 : GF_Err bxml_box_size(GF_Box *s)
221 : {
222 : GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s;
223 1 : if (!s) return GF_BAD_PARAM;
224 1 : ptr->size += ptr->data_length;
225 1 : return GF_OK;
226 : }
227 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
228 :
229 162 : GF_Box *iloc_box_new()
230 : {
231 324 : ISOM_DECL_BOX_ALLOC(GF_ItemLocationBox, GF_ISOM_BOX_TYPE_ILOC);
232 162 : tmp->location_entries = gf_list_new();
233 162 : return (GF_Box *)tmp;
234 : }
235 :
236 414 : void iloc_entry_del(GF_ItemLocationEntry *location)
237 : {
238 : u32 j, extent_count;
239 414 : extent_count = gf_list_count(location->extent_entries);
240 844 : for (j = 0; j < extent_count; j++) {
241 430 : GF_ItemExtentEntry *extent = (GF_ItemExtentEntry *)gf_list_get(location->extent_entries, j);
242 430 : gf_free(extent);
243 : }
244 414 : gf_list_del(location->extent_entries);
245 414 : gf_free(location);
246 414 : }
247 :
248 162 : void iloc_box_del(GF_Box *s)
249 : {
250 : u32 i, item_count;
251 : GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s;
252 162 : if (ptr == NULL) return;
253 162 : item_count = gf_list_count(ptr->location_entries);
254 572 : for (i = 0; i < item_count; i++) {
255 410 : GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i);
256 410 : iloc_entry_del(location);
257 : }
258 162 : gf_list_del(ptr->location_entries);
259 162 : gf_free(ptr);
260 : }
261 :
262 69 : GF_Err iloc_box_read(GF_Box *s, GF_BitStream *bs)
263 : {
264 : u32 item_count, extent_count, i, j;
265 : GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s;
266 :
267 69 : ISOM_DECREASE_SIZE(ptr, 2)
268 69 : ptr->offset_size = gf_bs_read_int(bs, 4);
269 69 : ptr->length_size = gf_bs_read_int(bs, 4);
270 69 : ptr->base_offset_size = gf_bs_read_int(bs, 4);
271 69 : if (ptr->version == 1 || ptr->version == 2) {
272 1 : ptr->index_size = gf_bs_read_int(bs, 4);
273 : } else {
274 68 : gf_bs_read_int(bs, 4);
275 : }
276 69 : if (ptr->version < 2) {
277 69 : ISOM_DECREASE_SIZE(ptr, 2)
278 69 : item_count = gf_bs_read_u16(bs);
279 : } else {
280 0 : ISOM_DECREASE_SIZE(ptr, 4)
281 0 : item_count = gf_bs_read_u32(bs);
282 : }
283 :
284 239 : for (i = 0; i < item_count; i++) {
285 170 : GF_ItemLocationEntry *location_entry = (GF_ItemLocationEntry *)gf_malloc(sizeof(GF_ItemLocationEntry));
286 170 : if (!location_entry) return GF_OUT_OF_MEM;
287 :
288 170 : gf_list_add(ptr->location_entries, location_entry);
289 170 : if (ptr->version < 2) {
290 170 : ISOM_DECREASE_SIZE(ptr, 2)
291 170 : location_entry->item_ID = gf_bs_read_u16(bs);
292 : } else {
293 0 : ISOM_DECREASE_SIZE(ptr, 4)
294 0 : location_entry->item_ID = gf_bs_read_u32(bs);
295 : }
296 170 : if (ptr->version == 1 || ptr->version == 2) {
297 10 : ISOM_DECREASE_SIZE(ptr, 2)
298 10 : location_entry->construction_method = gf_bs_read_u16(bs);
299 : }
300 : else {
301 160 : location_entry->construction_method = 0;
302 : }
303 170 : ISOM_DECREASE_SIZE(ptr, (2 + ptr->base_offset_size) )
304 170 : location_entry->data_reference_index = gf_bs_read_u16(bs);
305 170 : location_entry->base_offset = gf_bs_read_int(bs, 8*ptr->base_offset_size);
306 : #ifndef GPAC_DISABLE_ISOM_WRITE
307 170 : location_entry->original_base_offset = location_entry->base_offset;
308 : #endif
309 :
310 170 : ISOM_DECREASE_SIZE(ptr, 2)
311 170 : extent_count = gf_bs_read_u16(bs);
312 170 : location_entry->extent_entries = gf_list_new();
313 348 : for (j = 0; j < extent_count; j++) {
314 178 : GF_ItemExtentEntry *extent_entry = (GF_ItemExtentEntry *)gf_malloc(sizeof(GF_ItemExtentEntry));
315 178 : if (!extent_entry) return GF_OUT_OF_MEM;
316 :
317 178 : gf_list_add(location_entry->extent_entries, extent_entry);
318 178 : if ((ptr->version == 1 || ptr->version == 2) && ptr->index_size > 0) {
319 18 : ISOM_DECREASE_SIZE(ptr, ptr->index_size)
320 18 : extent_entry->extent_index = gf_bs_read_int(bs, 8 * ptr->index_size);
321 : }
322 : else {
323 160 : extent_entry->extent_index = 0;
324 : }
325 178 : ISOM_DECREASE_SIZE(ptr, (ptr->offset_size+ptr->length_size) )
326 :
327 178 : extent_entry->extent_offset = gf_bs_read_int(bs, 8*ptr->offset_size);
328 178 : extent_entry->extent_length = gf_bs_read_int(bs, 8*ptr->length_size);
329 : #ifndef GPAC_DISABLE_ISOM_WRITE
330 178 : extent_entry->original_extent_offset = extent_entry->extent_offset;
331 : #endif
332 : }
333 : }
334 : return GF_OK;
335 : }
336 :
337 : #ifndef GPAC_DISABLE_ISOM_WRITE
338 99 : GF_Err iloc_box_write(GF_Box *s, GF_BitStream *bs)
339 : {
340 : GF_Err e;
341 : u32 i, j, item_count, extent_count;
342 : GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s;
343 99 : if (!s) return GF_BAD_PARAM;
344 99 : e = gf_isom_full_box_write(s, bs);
345 99 : if (e) return e;
346 99 : gf_bs_write_int(bs, ptr->offset_size, 4);
347 99 : gf_bs_write_int(bs, ptr->length_size, 4);
348 99 : gf_bs_write_int(bs, ptr->base_offset_size, 4);
349 99 : gf_bs_write_int(bs, ptr->index_size, 4);
350 99 : item_count = gf_list_count(ptr->location_entries);
351 99 : if (ptr->version < 2) {
352 99 : gf_bs_write_u16(bs, item_count);
353 : }
354 : else {
355 0 : gf_bs_write_u32(bs, item_count);
356 : }
357 255 : for (i = 0; i < item_count; i++) {
358 255 : GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i);
359 255 : if (ptr->version < 2) {
360 255 : gf_bs_write_u16(bs, location->item_ID);
361 : }
362 : else {
363 0 : gf_bs_write_u32(bs, location->item_ID);
364 : }
365 255 : if (ptr->version == 1 || ptr->version == 2) {
366 10 : gf_bs_write_u16(bs, location->construction_method);
367 : }
368 255 : gf_bs_write_u16(bs, location->data_reference_index);
369 255 : gf_bs_write_long_int(bs, location->base_offset, 8*ptr->base_offset_size);
370 255 : extent_count = gf_list_count(location->extent_entries);
371 255 : gf_bs_write_u16(bs, extent_count);
372 518 : for (j=0; j<extent_count; j++) {
373 263 : GF_ItemExtentEntry *extent = (GF_ItemExtentEntry *)gf_list_get(location->extent_entries, j);
374 263 : if ((ptr->version == 1 || ptr->version == 2) && ptr->index_size > 0) {
375 18 : gf_bs_write_long_int(bs, extent->extent_index, 8 * ptr->index_size);
376 : }
377 263 : gf_bs_write_long_int(bs, extent->extent_offset, 8*ptr->offset_size);
378 263 : gf_bs_write_long_int(bs, extent->extent_length, 8*ptr->length_size);
379 : }
380 : }
381 : return GF_OK;
382 : }
383 :
384 291 : GF_Err iloc_box_size(GF_Box *s)
385 : {
386 : u32 i, item_count, extent_count;
387 : GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s;
388 291 : if (!s) return GF_BAD_PARAM;
389 291 : if (ptr->index_size) {
390 3 : ptr->version = 1;
391 : }
392 291 : item_count = gf_list_count(ptr->location_entries);
393 1048 : for (i = 0; i < item_count; i++) {
394 757 : GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i);
395 757 : if (location->construction_method) {
396 3 : ptr->version = 1;
397 : }
398 : if (location->item_ID > 0xFFFF) {
399 : ptr->version = 2;
400 : }
401 : }
402 291 : ptr->size += 4;
403 291 : if (ptr->version == 2) {
404 0 : ptr->size += 2; // 32 bits item count instead of 16 bits
405 : }
406 757 : for (i = 0; i < item_count; i++) {
407 757 : GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i);
408 757 : extent_count = gf_list_count(location->extent_entries);
409 757 : ptr->size += 6 + ptr->base_offset_size + extent_count*(ptr->offset_size + ptr->length_size);
410 757 : if (ptr->version == 2) {
411 0 : ptr->size += 2; //32 bits item ID instead of 16 bits
412 : }
413 757 : if (ptr->version == 1 || ptr->version == 2) {
414 30 : ptr->size += 2; // construction_method
415 30 : ptr->size += extent_count*ptr->index_size;
416 : }
417 : }
418 : return GF_OK;
419 : }
420 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
421 :
422 103 : GF_Box *pitm_box_new()
423 : {
424 206 : ISOM_DECL_BOX_ALLOC(GF_PrimaryItemBox, GF_ISOM_BOX_TYPE_PITM);
425 103 : return (GF_Box *)tmp;
426 : }
427 :
428 103 : void pitm_box_del(GF_Box *s)
429 : {
430 : GF_PrimaryItemBox *ptr = (GF_PrimaryItemBox *)s;
431 103 : if (ptr == NULL) return;
432 103 : gf_free(ptr);
433 : }
434 :
435 40 : GF_Err pitm_box_read(GF_Box *s, GF_BitStream *bs)
436 : {
437 : GF_PrimaryItemBox *ptr = (GF_PrimaryItemBox *)s;
438 40 : ISOM_DECREASE_SIZE(ptr, 2)
439 40 : ptr->item_ID = gf_bs_read_u16(bs);
440 40 : return GF_OK;
441 : }
442 :
443 : #ifndef GPAC_DISABLE_ISOM_WRITE
444 68 : GF_Err pitm_box_write(GF_Box *s, GF_BitStream *bs)
445 : {
446 : GF_Err e;
447 : GF_PrimaryItemBox *ptr = (GF_PrimaryItemBox *)s;
448 68 : if (!s) return GF_BAD_PARAM;
449 68 : e = gf_isom_full_box_write(s, bs);
450 68 : if (e) return e;
451 68 : gf_bs_write_u16(bs, ptr->item_ID);
452 68 : return GF_OK;
453 : }
454 :
455 197 : GF_Err pitm_box_size(GF_Box *s)
456 : {
457 : GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s;
458 197 : if (!s) return GF_BAD_PARAM;
459 197 : ptr->size += 2;
460 197 : return GF_OK;
461 : }
462 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
463 :
464 49 : GF_Box *ipro_box_new()
465 : {
466 98 : ISOM_DECL_BOX_ALLOC(GF_ItemProtectionBox, GF_ISOM_BOX_TYPE_IPRO);
467 49 : tmp->protection_information = gf_list_new();
468 49 : return (GF_Box *)tmp;
469 : }
470 :
471 49 : void ipro_box_del(GF_Box *s)
472 : {
473 : GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s;
474 49 : if (ptr == NULL) return;
475 49 : gf_list_del(ptr->protection_information);
476 49 : gf_free(ptr);
477 : }
478 :
479 23 : GF_Err ipro_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
480 : {
481 : GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s;
482 23 : if (a->type == GF_ISOM_BOX_TYPE_SINF) {
483 23 : BOX_FIELD_LIST_ASSIGN(protection_information)
484 : return GF_OK;
485 : }
486 : return GF_OK;
487 : }
488 24 : GF_Err ipro_box_read(GF_Box *s, GF_BitStream *bs)
489 : {
490 24 : ISOM_DECREASE_SIZE(s, 2)
491 24 : gf_bs_read_u16(bs);
492 24 : return gf_isom_box_array_read(s, bs);
493 : }
494 :
495 : #ifndef GPAC_DISABLE_ISOM_WRITE
496 24 : GF_Err ipro_box_write(GF_Box *s, GF_BitStream *bs)
497 : {
498 : u32 count;
499 : GF_Err e;
500 : GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s;
501 24 : if (!s) return GF_BAD_PARAM;
502 24 : e = gf_isom_full_box_write(s, bs);
503 24 : if (e) return e;
504 24 : count = gf_list_count(ptr->protection_information);
505 24 : gf_bs_write_u16(bs, count);
506 24 : return GF_OK;
507 : }
508 :
509 70 : GF_Err ipro_box_size(GF_Box *s)
510 : {
511 : GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s;
512 70 : u32 pos=0;
513 70 : gf_isom_check_position_list(s, ptr->protection_information, &pos);
514 70 : s->size += 2;
515 70 : return GF_OK;
516 : }
517 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
518 :
519 420 : GF_Box *infe_box_new()
520 : {
521 840 : ISOM_DECL_BOX_ALLOC(GF_ItemInfoEntryBox, GF_ISOM_BOX_TYPE_INFE);
522 420 : return (GF_Box *)tmp;
523 : }
524 :
525 420 : void infe_box_del(GF_Box *s)
526 : {
527 : GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s;
528 420 : if (ptr == NULL) return;
529 420 : if (ptr->item_name) gf_free(ptr->item_name);
530 420 : if (ptr->full_path) gf_free(ptr->full_path);
531 420 : if (ptr->content_type) gf_free(ptr->content_type);
532 420 : if (ptr->content_encoding) gf_free(ptr->content_encoding);
533 420 : gf_free(ptr);
534 : }
535 :
536 171 : GF_Err infe_box_read(GF_Box *s, GF_BitStream *bs)
537 : {
538 : char *buf;
539 : u32 buf_len, i, string_len, string_start;
540 : GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s;
541 :
542 171 : ISOM_DECREASE_SIZE(ptr, 4);
543 171 : ptr->item_ID = gf_bs_read_u16(bs);
544 171 : ptr->item_protection_index = gf_bs_read_u16(bs);
545 :
546 171 : if (ptr->version == 2) {
547 170 : ISOM_DECREASE_SIZE(ptr, 4);
548 170 : ptr->item_type = gf_bs_read_u32(bs);
549 : }
550 171 : buf_len = (u32) (ptr->size);
551 171 : buf = (char*)gf_malloc(buf_len);
552 171 : if (!buf) return GF_OUT_OF_MEM;
553 171 : if (buf_len != gf_bs_read_data(bs, buf, buf_len)) {
554 0 : gf_free(buf);
555 0 : return GF_ISOM_INVALID_FILE;
556 : }
557 : string_len = 1;
558 : string_start = 0;
559 1304 : for (i = 0; i < buf_len; i++) {
560 1304 : if (buf[i] == 0) {
561 233 : if (!ptr->item_name) {
562 171 : ptr->item_name = (char*)gf_malloc(sizeof(char)*string_len);
563 171 : if (!ptr->item_name) return GF_OUT_OF_MEM;
564 171 : memcpy(ptr->item_name, buf+string_start, string_len);
565 62 : } else if (!ptr->content_type) {
566 31 : ptr->content_type = (char*)gf_malloc(sizeof(char)*string_len);
567 31 : if (!ptr->content_type) return GF_OUT_OF_MEM;
568 31 : memcpy(ptr->content_type, buf+string_start, string_len);
569 : } else {
570 31 : ptr->content_encoding = (char*)gf_malloc(sizeof(char)*string_len);
571 31 : if (!ptr->content_encoding) return GF_OUT_OF_MEM;
572 31 : memcpy(ptr->content_encoding, buf+string_start, string_len);
573 : }
574 233 : string_start += string_len;
575 : string_len = 0;
576 233 : if (ptr->content_encoding && ptr->version == 1) {
577 : break;
578 : }
579 : }
580 1304 : string_len++;
581 : }
582 171 : gf_free(buf);
583 171 : if (!ptr->item_name || (!ptr->content_type && ptr->version < 2)) {
584 1 : GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[isoff] Infe without name or content type !\n"));
585 : }
586 : return GF_OK;
587 : }
588 :
589 : #ifndef GPAC_DISABLE_ISOM_WRITE
590 256 : GF_Err infe_box_write(GF_Box *s, GF_BitStream *bs)
591 : {
592 : GF_Err e;
593 : u32 len;
594 : GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s;
595 256 : if (!s) return GF_BAD_PARAM;
596 256 : e = gf_isom_full_box_write(s, bs);
597 256 : if (e) return e;
598 256 : if (ptr->version == 3) {
599 0 : gf_bs_write_u32(bs, ptr->item_ID);
600 : }
601 : else {
602 256 : gf_bs_write_u16(bs, ptr->item_ID);
603 : }
604 256 : gf_bs_write_u16(bs, ptr->item_protection_index);
605 256 : if (ptr->version >= 2) {
606 255 : gf_bs_write_u32(bs, ptr->item_type);
607 : }
608 256 : if (ptr->item_name) {
609 222 : len = (u32) strlen(ptr->item_name)+1;
610 222 : gf_bs_write_data(bs, ptr->item_name, len);
611 : } else {
612 34 : gf_bs_write_byte(bs, 0, 1);
613 : }
614 256 : if (ptr->item_type == GF_META_ITEM_TYPE_MIME || ptr->item_type == GF_META_ITEM_TYPE_URI) {
615 16 : if (ptr->content_type) {
616 16 : len = (u32)strlen(ptr->content_type) + 1;
617 16 : gf_bs_write_data(bs, ptr->content_type, len);
618 : }
619 : else {
620 0 : gf_bs_write_byte(bs, 0, 1);
621 : }
622 : }
623 256 : if (ptr->item_type == GF_META_ITEM_TYPE_MIME) {
624 16 : if (ptr->content_encoding) {
625 10 : len = (u32)strlen(ptr->content_encoding) + 1;
626 10 : gf_bs_write_data(bs, ptr->content_encoding, len);
627 : }
628 : else {
629 6 : gf_bs_write_byte(bs, 0, 1);
630 : }
631 : }
632 : return GF_OK;
633 : }
634 :
635 758 : GF_Err infe_box_size(GF_Box *s)
636 : {
637 : GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s;
638 758 : if (!s) return GF_BAD_PARAM;
639 758 : if (ptr->item_type) {
640 757 : ptr->version = 2;
641 : if (ptr->item_ID > 0xFFFF) {
642 : ptr->version = 3;
643 : }
644 : }
645 : else {
646 1 : ptr->version = 0;
647 : }
648 758 : ptr->size += 4;
649 758 : if (ptr->version == 3) {
650 0 : ptr->size += 2; // item_ID on 32 bits (+2 bytes)
651 : }
652 758 : if (ptr->version >= 2) {
653 757 : ptr->size += 4; // item_type size
654 : }
655 758 : if (ptr->item_name) ptr->size += strlen(ptr->item_name)+1;
656 101 : else ptr->size += 1;
657 758 : if (ptr->item_type == GF_META_ITEM_TYPE_MIME || ptr->item_type == GF_META_ITEM_TYPE_URI) {
658 36 : if (ptr->content_type) ptr->size += strlen(ptr->content_type) + 1;
659 0 : else ptr->size += 1;
660 : }
661 758 : if (ptr->item_type == GF_META_ITEM_TYPE_MIME) {
662 36 : if (ptr->content_encoding) ptr->size += strlen(ptr->content_encoding) + 1;
663 18 : else ptr->size += 1;
664 : }
665 : return GF_OK;
666 : }
667 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
668 :
669 161 : GF_Box *iinf_box_new()
670 : {
671 322 : ISOM_DECL_BOX_ALLOC(GF_ItemInfoBox, GF_ISOM_BOX_TYPE_IINF);
672 161 : tmp->item_infos = gf_list_new();
673 161 : return (GF_Box *)tmp;
674 : }
675 :
676 161 : void iinf_box_del(GF_Box *s)
677 : {
678 : GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s;
679 161 : if (ptr == NULL) return;
680 161 : gf_list_del(ptr->item_infos);
681 161 : gf_free(ptr);
682 : }
683 :
684 170 : GF_Err iinf_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
685 : {
686 : GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s;
687 :
688 170 : if (a->type == GF_ISOM_BOX_TYPE_INFE) {
689 170 : BOX_FIELD_LIST_ASSIGN(item_infos)
690 : return GF_OK;
691 : } else {
692 : return GF_OK;
693 : }
694 : }
695 :
696 69 : GF_Err iinf_box_read(GF_Box *s, GF_BitStream *bs)
697 : {
698 : GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s;
699 :
700 69 : if (ptr->version == 0) {
701 69 : ISOM_DECREASE_SIZE(s, 2)
702 69 : gf_bs_read_u16(bs);
703 : } else {
704 0 : ISOM_DECREASE_SIZE(s, 4)
705 0 : gf_bs_read_u32(bs);
706 : }
707 69 : return gf_isom_box_array_read(s, bs);
708 : }
709 :
710 : #ifndef GPAC_DISABLE_ISOM_WRITE
711 99 : GF_Err iinf_box_write(GF_Box *s, GF_BitStream *bs)
712 : {
713 : u32 count;
714 : GF_Err e;
715 : GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s;
716 99 : if (!s) return GF_BAD_PARAM;
717 99 : e = gf_isom_full_box_write(s, bs);
718 99 : if (e) return e;
719 99 : count = gf_list_count(ptr->item_infos);
720 99 : if (ptr->version == 0)
721 99 : gf_bs_write_u16(bs, count);
722 : else
723 0 : gf_bs_write_u32(bs, count);
724 :
725 : return GF_OK;
726 : }
727 :
728 291 : GF_Err iinf_box_size(GF_Box *s)
729 : {
730 291 : u32 pos=0;
731 : GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s;
732 291 : if (!s) return GF_BAD_PARAM;
733 291 : ptr->size += (ptr->version == 0) ? 2 : 4;
734 291 : gf_isom_check_position_list(s, ptr->item_infos, &pos);
735 291 : return GF_OK;
736 : }
737 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
738 :
739 34 : GF_Err iref_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
740 : {
741 : GF_ItemReferenceBox *ptr = (GF_ItemReferenceBox *)s;
742 34 : BOX_FIELD_LIST_ASSIGN(references)
743 : return GF_OK;
744 : }
745 :
746 63 : void iref_box_del(GF_Box *s)
747 : {
748 : GF_ItemReferenceBox *ptr = (GF_ItemReferenceBox *)s;
749 63 : if (ptr == NULL) return;
750 63 : gf_list_del(ptr->references);
751 63 : gf_free(ptr);
752 : }
753 :
754 :
755 26 : GF_Err iref_box_read(GF_Box *s, GF_BitStream *bs)
756 : {
757 26 : return gf_isom_box_array_read_ex(s, bs, s->type);
758 : }
759 :
760 63 : GF_Box *iref_box_new()
761 : {
762 126 : ISOM_DECL_BOX_ALLOC(GF_ItemReferenceBox, GF_ISOM_BOX_TYPE_IREF);
763 63 : tmp->references = gf_list_new();
764 63 : return (GF_Box *)tmp;
765 : }
766 :
767 : #ifndef GPAC_DISABLE_ISOM_WRITE
768 :
769 35 : GF_Err iref_box_write(GF_Box *s, GF_BitStream *bs)
770 : {
771 35 : return gf_isom_full_box_write(s, bs);
772 : }
773 :
774 103 : GF_Err iref_box_size(GF_Box *s)
775 : {
776 103 : u32 pos=0;
777 : GF_ItemReferenceBox *ptr = (GF_ItemReferenceBox *)s;
778 103 : gf_isom_check_position_list(s, ptr->references, &pos);
779 103 : return GF_OK;
780 : }
781 :
782 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
783 :
784 83 : void ireftype_box_del(GF_Box *s)
785 : {
786 : GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s;
787 83 : if (!ptr) return;
788 83 : if (ptr->to_item_IDs) gf_free(ptr->to_item_IDs);
789 83 : gf_free(ptr);
790 : }
791 :
792 34 : GF_Err ireftype_box_read(GF_Box *s, GF_BitStream *bs)
793 : {
794 : u32 i;
795 : GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s;
796 :
797 34 : ISOM_DECREASE_SIZE(ptr, 4)
798 34 : ptr->from_item_id = gf_bs_read_u16(bs);
799 34 : ptr->reference_count = gf_bs_read_u16(bs);
800 34 : if (ptr->size / 2 < ptr->reference_count)
801 : return GF_ISOM_INVALID_FILE;
802 :
803 34 : ptr->to_item_IDs = (u32 *)gf_malloc(ptr->reference_count * sizeof(u32));
804 34 : if (!ptr->to_item_IDs) return GF_OUT_OF_MEM;
805 :
806 42 : for (i=0; i < ptr->reference_count; i++) {
807 42 : ISOM_DECREASE_SIZE(ptr, 2)
808 42 : ptr->to_item_IDs[i] = gf_bs_read_u16(bs);
809 : }
810 : return GF_OK;
811 : }
812 :
813 83 : GF_Box *ireftype_box_new()
814 : {
815 166 : ISOM_DECL_BOX_ALLOC(GF_ItemReferenceTypeBox, GF_ISOM_BOX_TYPE_REFI);
816 83 : return (GF_Box *)tmp;
817 : }
818 :
819 : #ifndef GPAC_DISABLE_ISOM_WRITE
820 :
821 46 : GF_Err ireftype_box_write(GF_Box *s, GF_BitStream *bs)
822 : {
823 : GF_Err e;
824 : u32 i;
825 : GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s;
826 46 : ptr->type = ptr->reference_type;
827 46 : e = gf_isom_box_write_header(s, bs);
828 46 : ptr->type = GF_ISOM_BOX_TYPE_REFI;
829 46 : if (e) return e;
830 46 : gf_bs_write_u16(bs, ptr->from_item_id);
831 46 : gf_bs_write_u16(bs, ptr->reference_count);
832 136 : for (i = 0; i < ptr->reference_count; i++) {
833 90 : gf_bs_write_u16(bs, ptr->to_item_IDs[i]);
834 : }
835 : return GF_OK;
836 : }
837 :
838 :
839 132 : GF_Err ireftype_box_size(GF_Box *s)
840 : {
841 : GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s;
842 132 : ptr->size += 4 + (ptr->reference_count * sizeof(u16));
843 132 : return GF_OK;
844 : }
845 :
846 : #endif /*GPAC_DISABLE_ISOM_WRITE*/
847 : #endif /*GPAC_DISABLE_ISOM*/
848 :
|