1 /*
2 *			GPAC - Multimedia Framework C SDK
3 *
4 *          Authors: Cyril Concolato / Jean Le Feuvre
5 *			Copyright (c) Telecom ParisTech 2005-2012
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 
meta_New()30 GF_Box *meta_New()
31 {
32 	ISOM_DECL_BOX_ALLOC(GF_MetaBox, GF_ISOM_BOX_TYPE_META);
33 	gf_isom_full_box_init((GF_Box *)tmp);
34 	tmp->other_boxes = gf_list_new();
35 	return (GF_Box *)tmp;
36 }
37 
meta_del(GF_Box * s)38 void meta_del(GF_Box *s)
39 {
40 	GF_MetaBox *ptr = (GF_MetaBox *)s;
41 	if (ptr == NULL) return;
42 	gf_isom_box_del((GF_Box *)ptr->handler);
43 	if (ptr->primary_resource) gf_isom_box_del((GF_Box *)ptr->primary_resource);
44 	if (ptr->file_locations) gf_isom_box_del((GF_Box *)ptr->file_locations);
45 	if (ptr->item_locations) gf_isom_box_del((GF_Box *)ptr->item_locations);
46 	if (ptr->protections) gf_isom_box_del((GF_Box *)ptr->protections);
47 	if (ptr->item_infos) gf_isom_box_del((GF_Box *)ptr->item_infos);
48 	if (ptr->IPMP_control) gf_isom_box_del((GF_Box *)ptr->IPMP_control);
49 	if (ptr->item_refs) gf_isom_box_del((GF_Box *)ptr->item_refs);
50 	if (ptr->item_props) gf_isom_box_del((GF_Box *)ptr->item_props);
51 	gf_free(ptr);
52 }
53 
meta_AddBox(GF_Box * s,GF_Box * a)54 GF_Err meta_AddBox(GF_Box *s, GF_Box *a)
55 {
56 	GF_MetaBox *ptr = (GF_MetaBox *)s;
57 	switch (a->type) {
58 	case GF_ISOM_BOX_TYPE_HDLR:
59 		if (ptr->handler) return GF_ISOM_INVALID_FILE;
60 		ptr->handler = (GF_HandlerBox*)a;
61 		break;
62 	case GF_ISOM_BOX_TYPE_PITM:
63 		if (ptr->primary_resource) return GF_ISOM_INVALID_FILE;
64 		ptr->primary_resource = (GF_PrimaryItemBox*)a;
65 		break;
66 	case GF_ISOM_BOX_TYPE_DINF:
67 		if (ptr->file_locations) return GF_ISOM_INVALID_FILE;
68 		ptr->file_locations = (GF_DataInformationBox*)a;
69 		break;
70 	case GF_ISOM_BOX_TYPE_ILOC:
71 		if (ptr->item_locations) return GF_ISOM_INVALID_FILE;
72 		ptr->item_locations = (GF_ItemLocationBox*)a;
73 		break;
74 	case GF_ISOM_BOX_TYPE_IPRO:
75 		if (ptr->protections) return GF_ISOM_INVALID_FILE;
76 		ptr->protections = (GF_ItemProtectionBox*)a;
77 		break;
78 	case GF_ISOM_BOX_TYPE_IINF:
79 		if (ptr->item_infos) return GF_ISOM_INVALID_FILE;
80 		ptr->item_infos = (GF_ItemInfoBox*)a;
81 		break;
82 	case GF_ISOM_BOX_TYPE_IREF:
83 		if (ptr->item_refs) return GF_ISOM_INVALID_FILE;
84 		ptr->item_refs = (GF_ItemReferenceBox*)a;
85 		break;
86 	case GF_ISOM_BOX_TYPE_IPRP:
87 		if (ptr->item_props) return GF_ISOM_INVALID_FILE;
88 		ptr->item_props = (GF_ItemPropertiesBox*)a;
89 		break;
90 		//case ???: ptr->IPMP_control = (???*)a; break;
91 	case GF_ISOM_BOX_TYPE_XML:
92 	case GF_ISOM_BOX_TYPE_BXML:
93 	case GF_ISOM_BOX_TYPE_ILST:
94 	default:
95 		return gf_isom_box_add_default(s, a);
96 	}
97 	return GF_OK;
98 }
99 
meta_Read(GF_Box * s,GF_BitStream * bs)100 GF_Err meta_Read(GF_Box *s, GF_BitStream *bs)
101 {
102 	u32 next_size = gf_bs_peek_bits(bs, 32, 4);
103 	GF_Err e;
104 	/*try to hack around QT files which don't use a full box for meta*/
105 	if (next_size<s->size) {
106 		e = gf_isom_full_box_read(s, bs);
107 		if (e) return e;
108 	}
109 	return gf_isom_read_box_list(s, bs, meta_AddBox);
110 }
111 
112 #ifndef GPAC_DISABLE_ISOM_WRITE
meta_Write(GF_Box * s,GF_BitStream * bs)113 GF_Err meta_Write(GF_Box *s, GF_BitStream *bs)
114 {
115 	GF_Err e;
116 	GF_MetaBox *ptr = (GF_MetaBox *)s;
117 	if (!s) return GF_BAD_PARAM;
118 	e = gf_isom_full_box_write(s, bs);
119 	if (e) return e;
120 	if (ptr->handler) {
121 		e = gf_isom_box_write((GF_Box *)ptr->handler, bs);
122 		if (e) return e;
123 	}
124 	if (ptr->primary_resource) {
125 		e = gf_isom_box_write((GF_Box *)ptr->primary_resource, bs);
126 		if (e) return e;
127 	}
128 	if (ptr->file_locations) {
129 		e = gf_isom_box_write((GF_Box *)ptr->file_locations, bs);
130 		if (e) return e;
131 	}
132 	if (ptr->item_locations) {
133 		e = gf_isom_box_write((GF_Box *)ptr->item_locations, bs);
134 		if (e) return e;
135 	}
136 	if (ptr->protections) {
137 		e = gf_isom_box_write((GF_Box *)ptr->protections, bs);
138 		if (e) return e;
139 	}
140 	if (ptr->item_infos) {
141 		e = gf_isom_box_write((GF_Box *)ptr->item_infos, bs);
142 		if (e) return e;
143 	}
144 	if (ptr->IPMP_control) {
145 		e = gf_isom_box_write((GF_Box *)ptr->IPMP_control, bs);
146 		if (e) return e;
147 	}
148 	if (ptr->item_refs) {
149 		e = gf_isom_box_write((GF_Box *)ptr->item_refs, bs);
150 		if (e) return e;
151 	}
152 	if (ptr->item_props) {
153 		e = gf_isom_box_write((GF_Box *)ptr->item_props, bs);
154 		if (e) return e;
155 	}
156 	return GF_OK;
157 }
158 
meta_Size(GF_Box * s)159 GF_Err meta_Size(GF_Box *s)
160 {
161 	GF_Err e;
162 	GF_MetaBox *ptr = (GF_MetaBox *)s;
163 	if (!s) return GF_BAD_PARAM;
164 	e = gf_isom_full_box_get_size(s);
165 	if (e) return e;
166 	if (ptr->handler) {
167 		e = gf_isom_box_size((GF_Box *)ptr->handler);
168 		if (e) return e;
169 		ptr->size += ptr->handler->size;
170 	}
171 	if (ptr->primary_resource) {
172 		e = gf_isom_box_size((GF_Box *)ptr->primary_resource);
173 		if (e) return e;
174 		ptr->size += ptr->primary_resource->size;
175 	}
176 	if (ptr->file_locations) {
177 		e = gf_isom_box_size((GF_Box *)ptr->file_locations);
178 		if (e) return e;
179 		ptr->size += ptr->file_locations->size;
180 	}
181 	if (ptr->item_locations) {
182 		e = gf_isom_box_size((GF_Box *)ptr->item_locations);
183 		if (e) return e;
184 		ptr->size += ptr->item_locations->size;
185 	}
186 	if (ptr->protections) {
187 		e = gf_isom_box_size((GF_Box *)ptr->protections);
188 		if (e) return e;
189 		ptr->size += ptr->protections->size;
190 	}
191 	if (ptr->item_infos) {
192 		e = gf_isom_box_size((GF_Box *)ptr->item_infos);
193 		if (e) return e;
194 		ptr->size += ptr->item_infos->size;
195 	}
196 	if (ptr->IPMP_control) {
197 		e = gf_isom_box_size((GF_Box *)ptr->IPMP_control);
198 		if (e) return e;
199 		ptr->size += ptr->IPMP_control->size;
200 	}
201 	if (ptr->item_refs) {
202 		e = gf_isom_box_size((GF_Box *)ptr->item_refs);
203 		if (e) return e;
204 		ptr->size += ptr->item_refs->size;
205 	}
206 	if (ptr->item_props) {
207 		e = gf_isom_box_size((GF_Box *)ptr->item_props);
208 		if (e) return e;
209 		ptr->size += ptr->item_props->size;
210 	}
211 	return GF_OK;
212 }
213 #endif /*GPAC_DISABLE_ISOM_WRITE*/
214 
xml_New()215 GF_Box *xml_New()
216 {
217 	ISOM_DECL_BOX_ALLOC(GF_XMLBox, GF_ISOM_BOX_TYPE_XML);
218 	gf_isom_full_box_init((GF_Box *)tmp);
219 	return (GF_Box *)tmp;
220 }
221 
xml_del(GF_Box * s)222 void xml_del(GF_Box *s)
223 {
224 	GF_XMLBox *ptr = (GF_XMLBox *)s;
225 	if (ptr == NULL) return;
226 	if (ptr->xml_length && ptr->xml) gf_free(ptr->xml);
227 	gf_free(ptr);
228 }
229 
xml_Read(GF_Box * s,GF_BitStream * bs)230 GF_Err xml_Read(GF_Box *s, GF_BitStream *bs)
231 {
232 	GF_Err e;
233 	GF_XMLBox *ptr = (GF_XMLBox *)s;
234 	if (ptr == NULL) return GF_BAD_PARAM;
235 	e = gf_isom_full_box_read(s, bs);
236 	if (e) return e;
237 	ptr->xml_length = (u32)(ptr->size);
238 	ptr->xml = (char *)gf_malloc(sizeof(char)*ptr->xml_length);
239 	if (!ptr->xml) return GF_OUT_OF_MEM;
240 	gf_bs_read_data(bs, ptr->xml, ptr->xml_length);
241 	return GF_OK;
242 }
243 
244 #ifndef GPAC_DISABLE_ISOM_WRITE
xml_Write(GF_Box * s,GF_BitStream * bs)245 GF_Err xml_Write(GF_Box *s, GF_BitStream *bs)
246 {
247 	GF_Err e;
248 	GF_XMLBox *ptr = (GF_XMLBox *)s;
249 	if (!s) return GF_BAD_PARAM;
250 	e = gf_isom_full_box_write(s, bs);
251 	if (e) return e;
252 	if (ptr->xml_length) gf_bs_write_data(bs, ptr->xml, ptr->xml_length);
253 	return GF_OK;
254 }
255 
xml_Size(GF_Box * s)256 GF_Err xml_Size(GF_Box *s)
257 {
258 	GF_Err e;
259 	GF_XMLBox *ptr = (GF_XMLBox *)s;
260 	if (!s) return GF_BAD_PARAM;
261 	e = gf_isom_full_box_get_size(s);
262 	if (e) return e;
263 	ptr->size += ptr->xml_length;
264 	return GF_OK;
265 }
266 #endif /*GPAC_DISABLE_ISOM_WRITE*/
267 
bxml_New()268 GF_Box *bxml_New()
269 {
270 	ISOM_DECL_BOX_ALLOC(GF_BinaryXMLBox, GF_ISOM_BOX_TYPE_BXML);
271 	gf_isom_full_box_init((GF_Box *)tmp);
272 	return (GF_Box *)tmp;
273 }
274 
bxml_del(GF_Box * s)275 void bxml_del(GF_Box *s)
276 {
277 	GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s;
278 	if (ptr == NULL) return;
279 	if (ptr->data_length && ptr->data) gf_free(ptr->data);
280 	gf_free(ptr);
281 }
282 
bxml_Read(GF_Box * s,GF_BitStream * bs)283 GF_Err bxml_Read(GF_Box *s, GF_BitStream *bs)
284 {
285 	GF_Err e;
286 	GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s;
287 	e = gf_isom_full_box_read(s, bs);
288 	if (e) return e;
289 	ptr->data_length = (u32)(ptr->size);
290 	ptr->data = (char*)gf_malloc(sizeof(char)*ptr->data_length);
291 	if (!ptr->data) return GF_OUT_OF_MEM;
292 	gf_bs_read_data(bs, ptr->data, ptr->data_length);
293 	return GF_OK;
294 }
295 
296 #ifndef GPAC_DISABLE_ISOM_WRITE
bxml_Write(GF_Box * s,GF_BitStream * bs)297 GF_Err bxml_Write(GF_Box *s, GF_BitStream *bs)
298 {
299 	GF_Err e;
300 	GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s;
301 	if (!s) return GF_BAD_PARAM;
302 	e = gf_isom_full_box_write(s, bs);
303 	if (e) return e;
304 	if (ptr->data_length) gf_bs_write_data(bs, ptr->data, ptr->data_length);
305 	return GF_OK;
306 }
307 
bxml_Size(GF_Box * s)308 GF_Err bxml_Size(GF_Box *s)
309 {
310 	GF_Err e;
311 	GF_BinaryXMLBox *ptr = (GF_BinaryXMLBox *)s;
312 	if (!s) return GF_BAD_PARAM;
313 	e = gf_isom_full_box_get_size(s);
314 	if (e) return e;
315 	ptr->size += ptr->data_length;
316 	return GF_OK;
317 }
318 #endif /*GPAC_DISABLE_ISOM_WRITE*/
319 
iloc_New()320 GF_Box *iloc_New()
321 {
322 	ISOM_DECL_BOX_ALLOC(GF_ItemLocationBox, GF_ISOM_BOX_TYPE_ILOC);
323 	gf_isom_full_box_init((GF_Box *)tmp);
324 	tmp->location_entries = gf_list_new();
325 	return (GF_Box *)tmp;
326 }
327 
iloc_entry_del(GF_ItemLocationEntry * location)328 void iloc_entry_del(GF_ItemLocationEntry *location)
329 {
330 	u32 j, extent_count;
331 	extent_count = gf_list_count(location->extent_entries);
332 	for (j = 0; j < extent_count; j++) {
333 		GF_ItemExtentEntry *extent = (GF_ItemExtentEntry *)gf_list_get(location->extent_entries, j);
334 		gf_free(extent);
335 	}
336 	gf_list_del(location->extent_entries);
337 	gf_free(location);
338 }
339 
iloc_del(GF_Box * s)340 void iloc_del(GF_Box *s)
341 {
342 	u32 i, item_count;
343 	GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s;
344 	if (ptr == NULL) return;
345 	item_count = gf_list_count(ptr->location_entries);
346 	for (i = 0; i < item_count; i++) {
347 		GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i);
348 		iloc_entry_del(location);
349 	}
350 	gf_list_del(ptr->location_entries);
351 	gf_free(ptr);
352 }
353 
iloc_Read(GF_Box * s,GF_BitStream * bs)354 GF_Err iloc_Read(GF_Box *s, GF_BitStream *bs)
355 {
356 	GF_Err e;
357 	u32 item_count, extent_count, i, j;
358 	GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s;
359 	e = gf_isom_full_box_read(s, bs);
360 	if (e) return e;
361 	ptr->offset_size = gf_bs_read_int(bs, 4);
362 	ptr->length_size = gf_bs_read_int(bs, 4);
363 	ptr->base_offset_size = gf_bs_read_int(bs, 4);
364 	if (ptr->version == 1 || ptr->version == 2) {
365 		ptr->index_size = gf_bs_read_int(bs, 4);
366 	}
367 	else {
368 		gf_bs_read_int(bs, 4);
369 	}
370 	if (ptr->version < 2) {
371 		item_count = gf_bs_read_u16(bs);
372 	}
373 	else {
374 		item_count = gf_bs_read_u32(bs);
375 	}
376 	for (i = 0; i < item_count; i++) {
377 		GF_ItemLocationEntry *location_entry = (GF_ItemLocationEntry *)gf_malloc(sizeof(GF_ItemLocationEntry));
378 		gf_list_add(ptr->location_entries, location_entry);
379 		if (ptr->version < 2) {
380 			location_entry->item_ID = gf_bs_read_u16(bs);
381 		}
382 		else {
383 			location_entry->item_ID = gf_bs_read_u32(bs);
384 		}
385 		if (ptr->version == 1 || ptr->version == 2) {
386 			location_entry->construction_method = gf_bs_read_u16(bs);
387 		}
388 		else {
389 			location_entry->construction_method = 0;
390 		}
391 		location_entry->data_reference_index = gf_bs_read_u16(bs);
392 		location_entry->base_offset = gf_bs_read_int(bs, 8 * ptr->base_offset_size);
393 #ifndef GPAC_DISABLE_ISOM_WRITE
394 		location_entry->original_base_offset = location_entry->base_offset;
395 #endif
396 
397 		extent_count = gf_bs_read_u16(bs);
398 		location_entry->extent_entries = gf_list_new();
399 		for (j = 0; j < extent_count; j++) {
400 			GF_ItemExtentEntry *extent_entry = (GF_ItemExtentEntry *)gf_malloc(sizeof(GF_ItemExtentEntry));
401 			gf_list_add(location_entry->extent_entries, extent_entry);
402 			if ((ptr->version == 1 || ptr->version == 2) && ptr->index_size > 0) {
403 				extent_entry->extent_index = gf_bs_read_int(bs, 8 * ptr->index_size);;
404 			}
405 			else {
406 				extent_entry->extent_index = 0;
407 			}
408 			extent_entry->extent_offset = gf_bs_read_int(bs, 8 * ptr->offset_size);
409 			extent_entry->extent_length = gf_bs_read_int(bs, 8 * ptr->length_size);
410 #ifndef GPAC_DISABLE_ISOM_WRITE
411 			extent_entry->original_extent_offset = extent_entry->extent_offset;
412 #endif
413 		}
414 	}
415 	return GF_OK;
416 }
417 
418 #ifndef GPAC_DISABLE_ISOM_WRITE
iloc_Write(GF_Box * s,GF_BitStream * bs)419 GF_Err iloc_Write(GF_Box *s, GF_BitStream *bs)
420 {
421 	GF_Err e;
422 	u32 i, j, item_count, extent_count;
423 	GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s;
424 	if (!s) return GF_BAD_PARAM;
425 	e = gf_isom_full_box_write(s, bs);
426 	if (e) return e;
427 	gf_bs_write_int(bs, ptr->offset_size, 4);
428 	gf_bs_write_int(bs, ptr->length_size, 4);
429 	gf_bs_write_int(bs, ptr->base_offset_size, 4);
430 	gf_bs_write_int(bs, ptr->index_size, 4);
431 	item_count = gf_list_count(ptr->location_entries);
432 	if (ptr->version < 2) {
433 		gf_bs_write_u16(bs, item_count);
434 	}
435 	else {
436 		gf_bs_write_u32(bs, item_count);
437 	}
438 	for (i = 0; i < item_count; i++) {
439 		GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i);
440 		if (ptr->version < 2) {
441 			gf_bs_write_u16(bs, location->item_ID);
442 		}
443 		else {
444 			gf_bs_write_u32(bs, location->item_ID);
445 		}
446 		if (ptr->version == 1 || ptr->version == 2) {
447 			gf_bs_write_u16(bs, location->construction_method);
448 		}
449 		gf_bs_write_u16(bs, location->data_reference_index);
450 		gf_bs_write_long_int(bs, location->base_offset, 8 * ptr->base_offset_size);
451 		extent_count = gf_list_count(location->extent_entries);
452 		gf_bs_write_u16(bs, extent_count);
453 		for (j = 0; j<extent_count; j++) {
454 			GF_ItemExtentEntry *extent = (GF_ItemExtentEntry *)gf_list_get(location->extent_entries, j);
455 			if ((ptr->version == 1 || ptr->version == 2) && ptr->index_size > 0) {
456 				gf_bs_write_long_int(bs, extent->extent_index, 8 * ptr->index_size);
457 			}
458 			gf_bs_write_long_int(bs, extent->extent_offset, 8 * ptr->offset_size);
459 			gf_bs_write_long_int(bs, extent->extent_length, 8 * ptr->length_size);
460 		}
461 	}
462 	return GF_OK;
463 }
464 
iloc_Size(GF_Box * s)465 GF_Err iloc_Size(GF_Box *s)
466 {
467 	GF_Err e;
468 	u32 i, item_count, extent_count;
469 	GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s;
470 	if (!s) return GF_BAD_PARAM;
471 	e = gf_isom_full_box_get_size(s);
472 	if (e) return e;
473 	if (ptr->index_size) {
474 		ptr->version = 1;
475 	}
476 	item_count = gf_list_count(ptr->location_entries);
477 	for (i = 0; i < item_count; i++) {
478 		GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i);
479 		if (location->construction_method) {
480 			ptr->version = 1;
481 		}
482 		if (location->item_ID > 0xFFFF) {
483 			ptr->version = 2;
484 		}
485 	}
486 	ptr->size += 4;
487 	if (ptr->version == 2) {
488 		ptr->size += 2; // 32 bits item count instead of 16 bits
489 	}
490 	for (i = 0; i < item_count; i++) {
491 		GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i);
492 		extent_count = gf_list_count(location->extent_entries);
493 		ptr->size += 6 + ptr->base_offset_size + extent_count*(ptr->offset_size + ptr->length_size);
494 		if (ptr->version == 2) {
495 			ptr->size += 2; //32 bits item ID instead of 16 bits
496 		}
497 		if (ptr->version == 1 || ptr->version == 2) {
498 			ptr->size += 2; // construction_method
499 			ptr->size += extent_count*ptr->index_size;
500 		}
501 	}
502 	return GF_OK;
503 }
504 #endif /*GPAC_DISABLE_ISOM_WRITE*/
505 
pitm_New()506 GF_Box *pitm_New()
507 {
508 	ISOM_DECL_BOX_ALLOC(GF_PrimaryItemBox, GF_ISOM_BOX_TYPE_PITM);
509 	gf_isom_full_box_init((GF_Box *)tmp);
510 	return (GF_Box *)tmp;
511 }
512 
pitm_del(GF_Box * s)513 void pitm_del(GF_Box *s)
514 {
515 	GF_PrimaryItemBox *ptr = (GF_PrimaryItemBox *)s;
516 	if (ptr == NULL) return;
517 	gf_free(ptr);
518 }
519 
pitm_Read(GF_Box * s,GF_BitStream * bs)520 GF_Err pitm_Read(GF_Box *s, GF_BitStream *bs)
521 {
522 	GF_Err e;
523 	GF_PrimaryItemBox *ptr = (GF_PrimaryItemBox *)s;
524 	e = gf_isom_full_box_read(s, bs);
525 	if (e) return e;
526 	ptr->item_ID = gf_bs_read_u16(bs);
527 	return GF_OK;
528 }
529 
530 #ifndef GPAC_DISABLE_ISOM_WRITE
pitm_Write(GF_Box * s,GF_BitStream * bs)531 GF_Err pitm_Write(GF_Box *s, GF_BitStream *bs)
532 {
533 	GF_Err e;
534 	GF_PrimaryItemBox *ptr = (GF_PrimaryItemBox *)s;
535 	if (!s) return GF_BAD_PARAM;
536 	e = gf_isom_full_box_write(s, bs);
537 	if (e) return e;
538 	gf_bs_write_u16(bs, ptr->item_ID);
539 	return GF_OK;
540 }
541 
pitm_Size(GF_Box * s)542 GF_Err pitm_Size(GF_Box *s)
543 {
544 	GF_Err e;
545 	GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s;
546 	if (!s) return GF_BAD_PARAM;
547 	e = gf_isom_full_box_get_size(s);
548 	if (e) return e;
549 	ptr->size += 2;
550 	return GF_OK;
551 }
552 #endif /*GPAC_DISABLE_ISOM_WRITE*/
553 
ipro_New()554 GF_Box *ipro_New()
555 {
556 	ISOM_DECL_BOX_ALLOC(GF_ItemProtectionBox, GF_ISOM_BOX_TYPE_IPRO);
557 	gf_isom_full_box_init((GF_Box *)tmp);
558 	tmp->protection_information = gf_list_new();
559 	return (GF_Box *)tmp;
560 }
561 
ipro_del(GF_Box * s)562 void ipro_del(GF_Box *s)
563 {
564 	u32 count, i;
565 	GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s;
566 	if (ptr == NULL) return;
567 	count = gf_list_count(ptr->protection_information);
568 	for (i = 0; i < count; i++) {
569 		GF_Box *a = (GF_Box *)gf_list_get(ptr->protection_information, i);
570 		gf_isom_box_del(a);
571 	}
572 	gf_list_del(ptr->protection_information);
573 	gf_free(ptr);
574 }
575 
ipro_AddBox(GF_Box * s,GF_Box * a)576 GF_Err ipro_AddBox(GF_Box *s, GF_Box *a)
577 {
578 	GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s;
579 	if (a->type == GF_ISOM_BOX_TYPE_SINF)
580 		return gf_list_add(ptr->protection_information, a);
581 	else
582 		return gf_isom_box_add_default(s, a);
583 }
ipro_Read(GF_Box * s,GF_BitStream * bs)584 GF_Err ipro_Read(GF_Box *s, GF_BitStream *bs)
585 {
586 	GF_Err e;
587 	e = gf_isom_full_box_read(s, bs);
588 	if (e) return e;
589 	return gf_isom_read_box_list(s, bs, ipro_AddBox);
590 }
591 
592 #ifndef GPAC_DISABLE_ISOM_WRITE
ipro_Write(GF_Box * s,GF_BitStream * bs)593 GF_Err ipro_Write(GF_Box *s, GF_BitStream *bs)
594 {
595 	u32 count, i;
596 	GF_Err e;
597 	GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s;
598 	if (!s) return GF_BAD_PARAM;
599 	e = gf_isom_full_box_write(s, bs);
600 	if (e) return e;
601 	count = gf_list_count(ptr->protection_information);
602 	gf_bs_write_u16(bs, count);
603 	if (count) {
604 		for (i = 0; i < count; i++) {
605 			GF_Box *a = (GF_Box *)gf_list_get(ptr->protection_information, i);
606 			e = gf_isom_box_write(a, bs);
607 			if (e) return e;
608 		}
609 	}
610 	return GF_OK;
611 }
612 
ipro_Size(GF_Box * s)613 GF_Err ipro_Size(GF_Box *s)
614 {
615 	u32 i, count;
616 	GF_Err e;
617 	GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s;
618 	if (!s) return GF_BAD_PARAM;
619 	e = gf_isom_full_box_get_size(s);
620 	if (e) return e;
621 	ptr->size += 2;
622 	if ((count = gf_list_count(ptr->protection_information))) {
623 		for (i = 0; i < count; i++) {
624 			GF_Box *a = (GF_Box *)gf_list_get(ptr->protection_information, i);
625 			e = gf_isom_box_size(a);
626 			if (e) return e;
627 			ptr->size += a->size;
628 		}
629 	}
630 	return GF_OK;
631 }
632 #endif /*GPAC_DISABLE_ISOM_WRITE*/
633 
infe_New()634 GF_Box *infe_New()
635 {
636 	ISOM_DECL_BOX_ALLOC(GF_ItemInfoEntryBox, GF_ISOM_BOX_TYPE_INFE);
637 	gf_isom_full_box_init((GF_Box *)tmp);
638 	return (GF_Box *)tmp;
639 }
640 
infe_del(GF_Box * s)641 void infe_del(GF_Box *s)
642 {
643 	GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s;
644 	if (ptr == NULL) return;
645 	if (ptr->item_name) gf_free(ptr->item_name);
646 	if (ptr->full_path) gf_free(ptr->full_path);
647 	if (ptr->content_type) gf_free(ptr->content_type);
648 	if (ptr->content_encoding) gf_free(ptr->content_encoding);
649 	gf_free(ptr);
650 }
651 
infe_Read(GF_Box * s,GF_BitStream * bs)652 GF_Err infe_Read(GF_Box *s, GF_BitStream *bs)
653 {
654 	GF_Err e;
655 	char *buf;
656 	u32 buf_len, i, string_len, string_start;
657 	GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s;
658 	if (ptr == NULL) return GF_BAD_PARAM;
659 	e = gf_isom_full_box_read(s, bs);
660 	if (e) return e;
661 
662 	ptr->item_ID = gf_bs_read_u16(bs);
663 	ptr->item_protection_index = gf_bs_read_u16(bs);
664 	ptr->size -= 4;
665 	if (ptr->version == 2) {
666 		ptr->item_type = gf_bs_read_u32(bs);
667 		ptr->size -= 4;
668 	}
669 	buf_len = (u32)(ptr->size);
670 	buf = (char*)gf_malloc(buf_len);
671 	if (buf_len != gf_bs_read_data(bs, buf, buf_len)) {
672 		gf_free(buf);
673 		return GF_ISOM_INVALID_FILE;
674 	}
675 	string_len = 1;
676 	string_start = 0;
677 	for (i = 0; i < buf_len; i++) {
678 		if (buf[i] == 0) {
679 			if (!ptr->item_name) {
680 				ptr->item_name = (char*)gf_malloc(sizeof(char)*string_len);
681 				memcpy(ptr->item_name, buf + string_start, string_len);
682 			}
683 			else if (!ptr->content_type) {
684 				ptr->content_type = (char*)gf_malloc(sizeof(char)*string_len);
685 				memcpy(ptr->content_type, buf + string_start, string_len);
686 			}
687 			else {
688 				ptr->content_encoding = (char*)gf_malloc(sizeof(char)*string_len);
689 				memcpy(ptr->content_encoding, buf + string_start, string_len);
690 			}
691 			string_start += string_len;
692 			string_len = 0;
693 		}
694 		string_len++;
695 	}
696 	gf_free(buf);
697 	if (!ptr->item_name || (!ptr->content_type && ptr->version < 2)) return GF_ISOM_INVALID_FILE;
698 	return GF_OK;
699 }
700 
701 #ifndef GPAC_DISABLE_ISOM_WRITE
infe_Write(GF_Box * s,GF_BitStream * bs)702 GF_Err infe_Write(GF_Box *s, GF_BitStream *bs)
703 {
704 	GF_Err e;
705 	u32 len;
706 	GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s;
707 	if (!s) return GF_BAD_PARAM;
708 	e = gf_isom_full_box_write(s, bs);
709 	if (e) return e;
710 	if (ptr->version == 3) {
711 		gf_bs_write_u32(bs, ptr->item_ID);
712 	}
713 	else {
714 		gf_bs_write_u16(bs, ptr->item_ID);
715 	}
716 	gf_bs_write_u16(bs, ptr->item_protection_index);
717 	if (ptr->version >= 2) {
718 		gf_bs_write_u32(bs, ptr->item_type);
719 	}
720 	if (ptr->item_name) {
721 		len = (u32)strlen(ptr->item_name) + 1;
722 		gf_bs_write_data(bs, ptr->item_name, len);
723 	}
724 	else {
725 		gf_bs_write_byte(bs, 0, 1);
726 	}
727 	if (ptr->item_type == GF_4CC('m', 'i', 'm', 'e') || ptr->item_type == GF_4CC('u', 'r', 'i', ' ')) {
728 		if (ptr->content_type) {
729 			len = (u32)strlen(ptr->content_type) + 1;
730 			gf_bs_write_data(bs, ptr->content_type, len);
731 		}
732 		else {
733 			gf_bs_write_byte(bs, 0, 1);
734 		}
735 	}
736 	if (ptr->item_type == GF_4CC('m', 'i', 'm', 'e')) {
737 		if (ptr->content_encoding) {
738 			len = (u32)strlen(ptr->content_encoding) + 1;
739 			gf_bs_write_data(bs, ptr->content_encoding, len);
740 		}
741 		else {
742 			gf_bs_write_byte(bs, 0, 1);
743 		}
744 	}
745 	return GF_OK;
746 }
747 
infe_Size(GF_Box * s)748 GF_Err infe_Size(GF_Box *s)
749 {
750 	GF_Err e;
751 	GF_ItemInfoEntryBox *ptr = (GF_ItemInfoEntryBox *)s;
752 	if (!s) return GF_BAD_PARAM;
753 	e = gf_isom_full_box_get_size(s);
754 	if (e) return e;
755 	if (ptr->item_type) {
756 		ptr->version = 2;
757 		if (ptr->item_ID > 0xFFFF) {
758 			ptr->version = 3;
759 		}
760 	}
761 	else {
762 		ptr->version = 0;
763 	}
764 	ptr->size += 4;
765 	if (ptr->version == 3) {
766 		ptr->size += 2; // item_ID on 32 bits (+2 bytes)
767 	}
768 	if (ptr->version >= 2) {
769 		ptr->size += 4; // item_type size
770 	}
771 	if (ptr->item_name) ptr->size += strlen(ptr->item_name) + 1;
772 	else ptr->size += 1;
773 	if (ptr->item_type == GF_4CC('m', 'i', 'm', 'e') || ptr->item_type == GF_4CC('u', 'r', 'i', ' ')) {
774 		if (ptr->content_type) ptr->size += strlen(ptr->content_type) + 1;
775 		else ptr->size += 1;
776 	}
777 	if (ptr->item_type == GF_4CC('m', 'i', 'm', 'e')) {
778 		if (ptr->content_encoding) ptr->size += strlen(ptr->content_encoding) + 1;
779 		else ptr->size += 1;
780 	}
781 	return GF_OK;
782 }
783 #endif /*GPAC_DISABLE_ISOM_WRITE*/
784 
iinf_New()785 GF_Box *iinf_New()
786 {
787 	ISOM_DECL_BOX_ALLOC(GF_ItemInfoBox, GF_ISOM_BOX_TYPE_IINF);
788 	gf_isom_full_box_init((GF_Box *)tmp);
789 	tmp->item_infos = gf_list_new();
790 	return (GF_Box *)tmp;
791 }
792 
iinf_del(GF_Box * s)793 void iinf_del(GF_Box *s)
794 {
795 	u32 count, i;
796 	GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s;
797 	if (ptr == NULL) return;
798 	count = gf_list_count(ptr->item_infos);
799 	for (i = 0; i < count; i++) {
800 		GF_Box *a = (GF_Box *)gf_list_get(ptr->item_infos, i);
801 		gf_isom_box_del(a);
802 	}
803 	gf_list_del(ptr->item_infos);
804 	gf_free(ptr);
805 }
806 
iinf_Read(GF_Box * s,GF_BitStream * bs)807 GF_Err iinf_Read(GF_Box *s, GF_BitStream *bs)
808 {
809 	GF_Err e;
810 	GF_Box *a;
811 	u32 count;
812 	GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s;
813 
814 	e = gf_isom_full_box_read(s, bs);
815 	if (e) return e;
816 	if (ptr->version == 0) {
817 		count = gf_bs_read_u16(bs);
818 	}
819 	else {
820 		count = gf_bs_read_u32(bs);
821 	}
822 
823 	while (count) {
824 		e = gf_isom_parse_box(&a, bs);
825 		if (e) return e;
826 		if (ptr->size<a->size) return GF_ISOM_INVALID_FILE;
827 
828 		if (a->type == GF_ISOM_BOX_TYPE_INFE)
829 			gf_list_add(ptr->item_infos, a);
830 		else
831 			gf_isom_box_del(a);
832 		count--;
833 	}
834 	return GF_OK;
835 }
836 
837 #ifndef GPAC_DISABLE_ISOM_WRITE
iinf_Write(GF_Box * s,GF_BitStream * bs)838 GF_Err iinf_Write(GF_Box *s, GF_BitStream *bs)
839 {
840 	u32 count, i;
841 	GF_Err e;
842 	GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s;
843 	if (!s) return GF_BAD_PARAM;
844 	e = gf_isom_full_box_write(s, bs);
845 	if (e) return e;
846 	count = gf_list_count(ptr->item_infos);
847 	gf_bs_write_u16(bs, count);
848 	if (count) {
849 		for (i = 0; i < count; i++) {
850 			GF_Box *a = (GF_Box *)gf_list_get(ptr->item_infos, i);
851 			e = gf_isom_box_write(a, bs);
852 			if (e) return e;
853 		}
854 	}
855 	return GF_OK;
856 }
857 
iinf_Size(GF_Box * s)858 GF_Err iinf_Size(GF_Box *s)
859 {
860 	u32 i, count;
861 	GF_Err e;
862 	GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s;
863 	if (!s) return GF_BAD_PARAM;
864 	e = gf_isom_full_box_get_size(s);
865 	if (e) return e;
866 	ptr->size += 2;
867 	if ((count = gf_list_count(ptr->item_infos))) {
868 		for (i = 0; i < count; i++) {
869 			GF_Box *a = (GF_Box *)gf_list_get(ptr->item_infos, i);
870 			e = gf_isom_box_size(a);
871 			if (e) return e;
872 			ptr->size += a->size;
873 		}
874 	}
875 	return GF_OK;
876 }
877 #endif /*GPAC_DISABLE_ISOM_WRITE*/
878 
iref_AddBox(GF_Box * s,GF_Box * a)879 GF_Err iref_AddBox(GF_Box *s, GF_Box *a)
880 {
881 	GF_ItemReferenceBox *ptr = (GF_ItemReferenceBox *)s;
882 	return gf_list_add(ptr->references, a);
883 }
884 
iref_del(GF_Box * s)885 void iref_del(GF_Box *s)
886 {
887 	u32 count, i;
888 	GF_ItemReferenceBox *ptr = (GF_ItemReferenceBox *)s;
889 	if (ptr == NULL) return;
890 	count = gf_list_count(ptr->references);
891 	for (i = 0; i < count; i++) {
892 		GF_Box *a = (GF_Box *)gf_list_get(ptr->references, i);
893 		gf_isom_box_del(a);
894 	}
895 	gf_list_del(ptr->references);
896 	gf_free(ptr);
897 }
898 
899 
iref_Read(GF_Box * s,GF_BitStream * bs)900 GF_Err iref_Read(GF_Box *s, GF_BitStream *bs)
901 {
902 	GF_Err e;
903 	e = gf_isom_full_box_read(s, bs);
904 	if (e) return e;
905 	return gf_isom_read_box_list_ex(s, bs, iref_AddBox, s->type);
906 }
907 
iref_New()908 GF_Box *iref_New()
909 {
910 	ISOM_DECL_BOX_ALLOC(GF_ItemReferenceBox, GF_ISOM_BOX_TYPE_IREF);
911 	tmp->references = gf_list_new();
912 	return (GF_Box *)tmp;
913 }
914 
915 #ifndef GPAC_DISABLE_ISOM_WRITE
916 
iref_Write(GF_Box * s,GF_BitStream * bs)917 GF_Err iref_Write(GF_Box *s, GF_BitStream *bs)
918 {
919 	GF_Err e;
920 	u32 count, i;
921 	GF_ItemReferenceBox *ptr = (GF_ItemReferenceBox *)s;
922 	if (!s) return GF_BAD_PARAM;
923 	e = gf_isom_full_box_write(s, bs);
924 	if (e) return e;
925 	count = gf_list_count(ptr->references);
926 	for (i = 0; i < count; i++) {
927 		GF_Box *a = (GF_Box *)gf_list_get(ptr->references, i);
928 		e = gf_isom_box_write(a, bs);
929 		if (e) return e;
930 	}
931 	return e;
932 }
933 
iref_Size(GF_Box * s)934 GF_Err iref_Size(GF_Box *s)
935 {
936 	GF_Err e;
937 	u32 count, i;
938 	GF_ItemReferenceBox *ptr = (GF_ItemReferenceBox *)s;
939 	if (!s) return GF_BAD_PARAM;
940 	e = gf_isom_full_box_get_size(s);
941 	if (e) return e;
942 	count = gf_list_count(ptr->references);
943 	for (i = 0; i < count; i++) {
944 		GF_Box *a = (GF_Box *)gf_list_get(ptr->references, i);
945 		e = gf_isom_box_size(a);
946 		if (e) return e;
947 		s->size += a->size;
948 	}
949 	return e;
950 }
951 
952 #endif /*GPAC_DISABLE_ISOM_WRITE*/
953 
ireftype_del(GF_Box * s)954 void ireftype_del(GF_Box *s)
955 {
956 	GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s;
957 	if (!ptr) return;
958 	if (ptr->to_item_IDs) gf_free(ptr->to_item_IDs);
959 	gf_free(ptr);
960 }
961 
ireftype_Read(GF_Box * s,GF_BitStream * bs)962 GF_Err ireftype_Read(GF_Box *s, GF_BitStream *bs)
963 {
964 	u32 bytesToRead;
965 	u32 i;
966 	GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s;
967 
968 	bytesToRead = (u32)(ptr->size);
969 	if (!bytesToRead) return GF_OK;
970 
971 	ptr->from_item_id = gf_bs_read_u16(bs);
972 	ptr->reference_count = gf_bs_read_u16(bs);
973 	ptr->to_item_IDs = (u32 *)gf_malloc(ptr->reference_count * sizeof(u32));
974 	if (!ptr->to_item_IDs) return GF_OUT_OF_MEM;
975 
976 	for (i = 0; i < ptr->reference_count; i++) {
977 		ptr->to_item_IDs[i] = gf_bs_read_u16(bs);
978 	}
979 	return GF_OK;
980 }
981 
ireftype_New()982 GF_Box *ireftype_New()
983 {
984 	ISOM_DECL_BOX_ALLOC(GF_ItemReferenceTypeBox, GF_ISOM_BOX_TYPE_REFI);
985 	return (GF_Box *)tmp;
986 }
987 
988 #ifndef GPAC_DISABLE_ISOM_WRITE
989 
ireftype_Write(GF_Box * s,GF_BitStream * bs)990 GF_Err ireftype_Write(GF_Box *s, GF_BitStream *bs)
991 {
992 	GF_Err e;
993 	u32 i;
994 	GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s;
995 	ptr->type = ptr->reference_type;
996 	e = gf_isom_box_write_header(s, bs);
997 	ptr->type = GF_ISOM_BOX_TYPE_REFI;
998 	if (e) return e;
999 	gf_bs_write_u16(bs, ptr->from_item_id);
1000 	gf_bs_write_u16(bs, ptr->reference_count);
1001 	for (i = 0; i < ptr->reference_count; i++) {
1002 		gf_bs_write_u16(bs, ptr->to_item_IDs[i]);
1003 	}
1004 	return GF_OK;
1005 }
1006 
1007 
ireftype_Size(GF_Box * s)1008 GF_Err ireftype_Size(GF_Box *s)
1009 {
1010 	GF_Err e;
1011 	GF_ItemReferenceTypeBox *ptr = (GF_ItemReferenceTypeBox *)s;
1012 	e = gf_isom_box_get_size(s);
1013 	if (e) return e;
1014 	ptr->size += 4 + (ptr->reference_count * sizeof(u16));
1015 	return GF_OK;
1016 }
1017 
1018 #endif /*GPAC_DISABLE_ISOM_WRITE*/
1019 #endif /*GPAC_DISABLE_ISOM*/
1020 
1021