1 /*
2 *			GPAC - Multimedia Framework C SDK
3 *
4 *			Authors: Jean Le Feuvre
5 *			Copyright (c) Telecom ParisTech 2006-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 
ilst_del(GF_Box * s)30 void ilst_del(GF_Box *s)
31 {
32 	GF_ItemListBox *ptr = (GF_ItemListBox *)s;
33 	if (ptr == NULL) return;
34 	gf_free(ptr);
35 }
36 
ilst_Read(GF_Box * s,GF_BitStream * bs)37 GF_Err ilst_Read(GF_Box *s, GF_BitStream *bs)
38 {
39 	GF_Err e;
40 	u32 sub_type;
41 	GF_Box *a;
42 	GF_ItemListBox *ptr = (GF_ItemListBox *)s;
43 	while (ptr->size) {
44 		/*if no ilst type coded, break*/
45 		sub_type = gf_bs_peek_bits(bs, 32, 0);
46 		if (sub_type) {
47 			e = gf_isom_parse_box(&a, bs);
48 			if (e) return e;
49 			if (ptr->size<a->size) return GF_ISOM_INVALID_FILE;
50 			ptr->size -= a->size;
51 			gf_list_add(ptr->other_boxes, a);
52 		}
53 		else {
54 			gf_bs_read_u32(bs);
55 			ptr->size -= 4;
56 		}
57 	}
58 	return GF_OK;
59 }
60 
ilst_New()61 GF_Box *ilst_New()
62 {
63 	ISOM_DECL_BOX_ALLOC(GF_ItemListBox, GF_ISOM_BOX_TYPE_ILST);
64 	tmp->other_boxes = gf_list_new();
65 	return (GF_Box *)tmp;
66 }
67 
68 #ifndef GPAC_DISABLE_ISOM_WRITE
69 
ilst_Write(GF_Box * s,GF_BitStream * bs)70 GF_Err ilst_Write(GF_Box *s, GF_BitStream *bs)
71 {
72 	GF_Err e;
73 	//	GF_ItemListBox *ptr = (GF_ItemListBox *)s;
74 
75 	e = gf_isom_box_write_header(s, bs);
76 	if (e) return e;
77 
78 	return GF_OK;
79 }
80 
81 
ilst_Size(GF_Box * s)82 GF_Err ilst_Size(GF_Box *s)
83 {
84 	GF_Err e;
85 	//	GF_ItemListBox *ptr = (GF_ItemListBox *)s;
86 
87 	e = gf_isom_box_get_size(s);
88 	if (e) return e;
89 
90 	return GF_OK;
91 }
92 
93 #endif /*GPAC_DISABLE_ISOM_WRITE*/
94 
ListItem_del(GF_Box * s)95 void ListItem_del(GF_Box *s)
96 {
97 	GF_ListItemBox *ptr = (GF_ListItemBox *)s;
98 	if (ptr == NULL) return;
99 	if (ptr->data != NULL) {
100 		if (ptr->data->data) gf_free(ptr->data->data);
101 		gf_free(ptr->data);
102 	}
103 	gf_free(ptr);
104 }
105 
ListItem_Read(GF_Box * s,GF_BitStream * bs)106 GF_Err ListItem_Read(GF_Box *s, GF_BitStream *bs)
107 {
108 	GF_Err e;
109 	u32 sub_type;
110 	GF_Box *a = NULL;
111 	GF_ListItemBox *ptr = (GF_ListItemBox *)s;
112 
113 	/*iTunes way: there's a data atom containing the data*/
114 	sub_type = gf_bs_peek_bits(bs, 32, 4);
115 	if (sub_type == GF_ISOM_BOX_TYPE_DATA) {
116 		e = gf_isom_parse_box(&a, bs);
117 		if (e) return e;
118 		if (ptr->size<a->size) return GF_ISOM_INVALID_FILE;
119 		ptr->size -= a->size;
120 
121 		if (a && ptr->data) gf_isom_box_del((GF_Box *)ptr->data);
122 		ptr->data = (GF_DataBox *)a;
123 	}
124 	/*QT way*/
125 	else {
126 		ptr->data->type = 0;
127 		ptr->data->dataSize = gf_bs_read_u16(bs);
128 		gf_bs_read_u16(bs);
129 		ptr->data->data = (char *)gf_malloc(sizeof(char)*(ptr->data->dataSize + 1));
130 		gf_bs_read_data(bs, ptr->data->data, ptr->data->dataSize);
131 		ptr->data->data[ptr->data->dataSize] = 0;
132 		ptr->size -= ptr->data->dataSize;
133 	}
134 	return GF_OK;
135 }
136 
ListItem_New(u32 type)137 GF_Box *ListItem_New(u32 type)
138 {
139 	ISOM_DECL_BOX_ALLOC(GF_ListItemBox, type);
140 
141 	tmp->data = (GF_DataBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_DATA);
142 
143 	if (tmp->data == NULL) {
144 		gf_free(tmp);
145 		return NULL;
146 	}
147 
148 	return (GF_Box *)tmp;
149 }
150 
151 #ifndef GPAC_DISABLE_ISOM_WRITE
152 
ListItem_Write(GF_Box * s,GF_BitStream * bs)153 GF_Err ListItem_Write(GF_Box *s, GF_BitStream *bs)
154 {
155 	GF_Err e;
156 	GF_ListItemBox *ptr = (GF_ListItemBox *)s;
157 
158 	e = gf_isom_box_write_header(s, bs);
159 	if (e) return e;
160 
161 	/*iTune way*/
162 	if (ptr->data->type) return gf_isom_box_write((GF_Box*)ptr->data, bs);
163 	/*QT way*/
164 	gf_bs_write_u16(bs, ptr->data->dataSize);
165 	gf_bs_write_u16(bs, 0);
166 	gf_bs_write_data(bs, ptr->data->data, ptr->data->dataSize);
167 	return GF_OK;
168 }
169 
ListItem_Size(GF_Box * s)170 GF_Err ListItem_Size(GF_Box *s)
171 {
172 	GF_Err e;
173 	GF_ListItemBox *ptr = (GF_ListItemBox *)s;
174 
175 	e = gf_isom_box_get_size(s);
176 	if (e) return e;
177 
178 	/*iTune way*/
179 	if (ptr->data && ptr->data->type) {
180 		e = gf_isom_box_size((GF_Box *)ptr->data);
181 		if (e) return e;
182 		ptr->size += ptr->data->size;
183 	}
184 	/*QT way*/
185 	else if (ptr->data) {
186 		ptr->size += ptr->data->dataSize + 4;
187 	}
188 	return GF_OK;
189 }
190 
191 #endif /*GPAC_DISABLE_ISOM_WRITE*/
192 
data_del(GF_Box * s)193 void data_del(GF_Box *s)
194 {
195 	GF_DataBox *ptr = (GF_DataBox *)s;
196 	if (ptr == NULL) return;
197 	if (ptr->data)
198 		gf_free(ptr->data);
199 	gf_free(ptr);
200 
201 }
202 
data_Read(GF_Box * s,GF_BitStream * bs)203 GF_Err data_Read(GF_Box *s, GF_BitStream *bs)
204 {
205 	GF_Err e;
206 	GF_DataBox *ptr = (GF_DataBox *)s;
207 
208 	e = gf_isom_full_box_read(s, bs);
209 	if (e) return e;
210 	ptr->reserved = gf_bs_read_int(bs, 32);
211 	ptr->size -= 4;
212 	if (ptr->size) {
213 		ptr->dataSize = (u32)ptr->size;
214 		ptr->data = (char*)gf_malloc(ptr->dataSize * sizeof(ptr->data[0]) + 1);
215 		if (ptr->data == NULL) return GF_OUT_OF_MEM;
216 		ptr->data[ptr->dataSize] = 0;
217 		gf_bs_read_data(bs, ptr->data, ptr->dataSize);
218 	}
219 
220 	return GF_OK;
221 }
222 
data_New()223 GF_Box *data_New()
224 {
225 	ISOM_DECL_BOX_ALLOC(GF_DataBox, GF_ISOM_BOX_TYPE_DATA);
226 
227 	gf_isom_full_box_init((GF_Box *)tmp);
228 
229 	return (GF_Box *)tmp;
230 }
231 
232 #ifndef GPAC_DISABLE_ISOM_WRITE
233 
data_Write(GF_Box * s,GF_BitStream * bs)234 GF_Err data_Write(GF_Box *s, GF_BitStream *bs)
235 {
236 	GF_Err e;
237 	GF_DataBox *ptr = (GF_DataBox *)s;
238 
239 	e = gf_isom_full_box_write(s, bs);
240 	if (e) return e;
241 	gf_bs_write_int(bs, ptr->reserved, 32);
242 	if (ptr->data != NULL && ptr->dataSize > 0) {
243 		gf_bs_write_data(bs, ptr->data, ptr->dataSize);
244 	}
245 	return GF_OK;
246 }
247 
data_Size(GF_Box * s)248 GF_Err data_Size(GF_Box *s)
249 {
250 	GF_Err e;
251 	GF_DataBox *ptr = (GF_DataBox *)s;
252 	e = gf_isom_full_box_get_size(s);
253 	if (e) return e;
254 	ptr->size += 4;
255 	if (ptr->data != NULL && ptr->dataSize > 0) {
256 		ptr->size += ptr->dataSize;
257 	}
258 	return GF_OK;
259 }
260 
261 #endif /*GPAC_DISABLE_ISOM_WRITE*/
262 
gf_isom_apple_get_meta_extensions(GF_ISOFile * mov)263 GF_MetaBox *gf_isom_apple_get_meta_extensions(GF_ISOFile *mov)
264 {
265 	u32 i;
266 	GF_MetaBox *meta;
267 	GF_UserDataMap *map;
268 
269 	if (!mov || !mov->moov) return NULL;
270 
271 	if (!mov->moov->udta) return NULL;
272 	map = udta_getEntry(mov->moov->udta, GF_ISOM_BOX_TYPE_META, NULL);
273 	if (!map) return NULL;
274 
275 	for (i = 0; i < gf_list_count(map->other_boxes); i++) {
276 		meta = (GF_MetaBox*)gf_list_get(map->other_boxes, i);
277 
278 		if (meta != NULL && meta->handler != NULL && meta->handler->handlerType == GF_ISOM_HANDLER_TYPE_MDIR) return meta;
279 	}
280 
281 	return NULL;
282 }
283 
284 #ifndef GPAC_DISABLE_ISOM_WRITE
gf_isom_apple_create_meta_extensions(GF_ISOFile * mov)285 GF_MetaBox *gf_isom_apple_create_meta_extensions(GF_ISOFile *mov)
286 {
287 	GF_Err e;
288 	u32 i;
289 	GF_MetaBox *meta;
290 	GF_UserDataMap *map;
291 
292 	if (!mov || !mov->moov) return NULL;
293 
294 	if (!mov->moov->udta) {
295 		e = moov_AddBox((GF_Box*)mov->moov, gf_isom_box_new(GF_ISOM_BOX_TYPE_UDTA));
296 		if (e) return NULL;
297 	}
298 
299 	map = udta_getEntry(mov->moov->udta, GF_ISOM_BOX_TYPE_META, NULL);
300 	if (map) {
301 		for (i = 0; i < gf_list_count(map->other_boxes); i++) {
302 			meta = (GF_MetaBox*)gf_list_get(map->other_boxes, i);
303 
304 			if (meta != NULL && meta->handler != NULL && meta->handler->handlerType == GF_ISOM_HANDLER_TYPE_MDIR) return meta;
305 		}
306 	}
307 
308 	meta = (GF_MetaBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_META);
309 
310 	if (meta != NULL) {
311 		meta->handler = (GF_HandlerBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_HDLR);
312 		if (meta->handler == NULL) {
313 			gf_isom_box_del((GF_Box *)meta);
314 			return NULL;
315 		}
316 		meta->handler->handlerType = GF_ISOM_HANDLER_TYPE_MDIR;
317 		if (!meta->other_boxes) meta->other_boxes = gf_list_new();
318 		gf_list_add(meta->other_boxes, gf_isom_box_new(GF_ISOM_BOX_TYPE_ILST));
319 		udta_AddBox(mov->moov->udta, (GF_Box *)meta);
320 	}
321 
322 	return meta;
323 }
324 #endif /*GPAC_DISABLE_ISOM_WRITE*/
325 
326 
327 #endif /*GPAC_DISABLE_ISOM*/
328